updated on Sat Jan 14 12:12:45 UTC 2012
[aur-mirror.git] / vimgdb / vim72gdb.diff
blob7e48be29169f2759b600af3c60b0300876cf1b63
2 Property changes on: src/netbeans.c
3 ___________________________________________________________________
4 Name: svn:keywords
5 + Id
8 Property changes on: src/term.c
9 ___________________________________________________________________
10 Name: svn:keywords
11 + Id
14 Property changes on: src/term.h
15 ___________________________________________________________________
16 Name: svn:keywords
17 + Id
20 Property changes on: src/digraph.c
21 ___________________________________________________________________
22 Name: svn:keywords
23 + Id
26 Property changes on: src/ex_docmd.c
27 ___________________________________________________________________
28 Name: svn:keywords
29 + Id
32 Property changes on: src/ex_cmds.c
33 ___________________________________________________________________
34 Name: svn:keywords
35 + Id
38 Property changes on: src/message.c
39 ___________________________________________________________________
40 Name: svn:keywords
41 + Id
44 Property changes on: src/ex_cmds.h
45 ___________________________________________________________________
46 Name: svn:keywords
47 + Id
50 Property changes on: src/mark.c
51 ___________________________________________________________________
52 Name: svn:keywords
53 + Id
56 Property changes on: src/ascii.h
57 ___________________________________________________________________
58 Name: svn:keywords
59 + Id
62 Property changes on: src/termlib.c
63 ___________________________________________________________________
64 Name: svn:keywords
65 + Id
68 Property changes on: src/if_perlsfio.c
69 ___________________________________________________________________
70 Name: svn:keywords
71 + Id
74 Property changes on: src/menu.c
75 ___________________________________________________________________
76 Name: svn:keywords
77 + Id
80 Property changes on: src/ex_cmds2.c
81 ___________________________________________________________________
82 Name: svn:keywords
83 + Id
85 Index: src/configure.in
86 ===================================================================
87 --- src/configure.in (.../vendor/vim/current) (revision 223)
88 +++ src/configure.in (.../trunk/vim) (revision 223)
89 @@ -986,6 +986,13 @@
90 AC_DEFINE(FEAT_CSCOPE)
93 +dnl FEAT_GDB defined later
94 +AC_MSG_CHECKING(--enable-gdb argument)
95 +AC_ARG_ENABLE(gdb,
96 + [ --enable-gdb Include GDB support.], ,
97 + [enable_gdb="no"])
98 +AC_MSG_RESULT($enable_gdb)
100 AC_MSG_CHECKING(--enable-workshop argument)
101 AC_ARG_ENABLE(workshop,
102 [ --enable-workshop Include Sun Visual Workshop support.], ,
103 @@ -2006,6 +2013,20 @@
104 AC_SUBST(GUITYPE)
105 AC_SUBST(GUI_X_LIBS)
107 +dnl do not add pty.o when a GUI is used
108 +if test "$enable_gdb" = "yes"; then
109 + AC_DEFINE(FEAT_GDB)
110 + if test "x$GUITYPE" = "xNONE"; then
111 + GDB_SRC="gdb.c clewn/gdb_lvl2.c clewn/gdb_lvl3.c clewn/misc.c clewn/obstack.c pty.c"
112 + GDB_OBJ="objects/gdb.o objects/gdb_lvl2.o objects/gdb_lvl3.o objects/misc.o objects/obstack.o objects/pty.o"
113 + else
114 + GDB_SRC="gdb.c clewn/gdb_lvl2.c clewn/gdb_lvl3.c clewn/misc.c clewn/obstack.c"
115 + GDB_OBJ="objects/gdb.o objects/gdb_lvl2.o objects/gdb_lvl3.o objects/misc.o objects/obstack.o"
116 + fi
117 + AC_SUBST(GDB_SRC)
118 + AC_SUBST(GDB_OBJ)
121 if test "$enable_workshop" = "yes" -a -n "$SKIP_MOTIF"; then
122 AC_MSG_ERROR([cannot use workshop without Motif])
125 Property changes on: src/hangulin.c
126 ___________________________________________________________________
127 Name: svn:keywords
128 + Id
131 Property changes on: src/move.c
132 ___________________________________________________________________
133 Name: svn:keywords
134 + Id
136 Index: src/option.c
137 ===================================================================
138 --- src/option.c (.../vendor/vim/current) (revision 223)
139 +++ src/option.c (.../trunk/vim) (revision 223)
140 @@ -524,6 +524,11 @@
141 {(char_u *)0L, (char_u *)0L}
142 #endif
143 SCRIPTID_INIT},
144 +#ifdef FEAT_GDB
145 + {"asm", NULL, P_NUM|P_VI_DEF,
146 + (char_u *)&p_asm, PV_NONE,
147 + {(char_u *)10L, (char_u *)0L}},
148 +#endif
149 #ifdef FEAT_AUTOCHDIR
150 {"autochdir", "acd", P_BOOL|P_VI_DEF,
151 (char_u *)&p_acd, PV_NONE,
152 @@ -1153,6 +1158,14 @@
153 {(char_u *)FALSE, (char_u *)0L}
154 #endif
155 SCRIPTID_INIT},
156 +#ifdef FEAT_GDB
157 + {"gdbvariables", "gdbvar",P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
158 + (char_u *)&p_gvar, PV_NONE,
159 + {(char_u *)"gdb-variables", (char_u *)0L} },
160 + {"gdbprg", "gdp", P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
161 + (char_u *)&p_gdp, PV_NONE,
162 + {(char_u *)"gdb", (char_u *)0L} },
163 +#endif
164 {"gdefault", "gd", P_BOOL|P_VI_DEF|P_VIM,
165 (char_u *)&p_gd, PV_NONE,
166 {(char_u *)FALSE, (char_u *)0L}},
168 Property changes on: src/option.c
169 ___________________________________________________________________
170 Name: svn:keywords
171 + Id
174 Property changes on: src/workshop.c
175 ___________________________________________________________________
176 Name: svn:keywords
177 + Id
179 Index: src/option.h
180 ===================================================================
181 --- src/option.h (.../vendor/vim/current) (revision 223)
182 +++ src/option.h (.../trunk/vim) (revision 223)
183 @@ -558,6 +558,11 @@
184 EXTERN char_u *p_isp; /* 'isprint' */
185 EXTERN int p_js; /* 'joinspaces' */
186 EXTERN char_u *p_kp; /* 'keywordprg' */
187 +#ifdef FEAT_GDB
188 +EXTERN long p_asm; /* 'asm' */
189 +EXTERN char_u *p_gvar; /* 'gdbvariables' */
190 +EXTERN char_u *p_gdp; /* 'gdbprg' */
191 +#endif
192 #ifdef FEAT_VISUAL
193 EXTERN char_u *p_km; /* 'keymodel' */
194 #endif
196 Property changes on: src/option.h
197 ___________________________________________________________________
198 Name: svn:keywords
199 + Id
202 Property changes on: src/workshop.h
203 ___________________________________________________________________
204 Name: svn:keywords
205 + Id
207 Index: src/proto/gdb.pro
208 ===================================================================
209 --- src/proto/gdb.pro (.../vendor/vim/current) (revision 0)
210 +++ src/proto/gdb.pro (.../trunk/vim) (revision 223)
211 @@ -0,0 +1,22 @@
212 +/* gdb.c */
213 +gdb_handle_T *gdb_new __ARGS((void));
214 +void gdb_delete __ARGS((gdb_handle_T **));
215 +int gdb_isrunning __ARGS((gdb_handle_T *));
216 +int gdb_fd __ARGS((gdb_handle_T *));
217 +pid_t gdb_pid __ARGS((gdb_handle_T *));
218 +int gdb_isbuffer __ARGS((gdb_handle_T *, buf_T *));
219 +int gdb_allowed __ARGS((gdb_handle_T *));
220 +int gdb_event __ARGS((gdb_handle_T *));
221 +int gdb_sigchld __ARGS((gdb_handle_T *));
222 +void gdb_set_event __ARGS((gdb_handle_T *, int));
223 +void gdb_set_sigchld __ARGS((gdb_handle_T *, int));
224 +int gdb_safe_vgetc __ARGS((gdb_handle_T *));
225 +void gdb_buffer_free __ARGS((gdb_handle_T *, buf_T *));
226 +void gdb_label __ARGS((gdb_handle_T *, buf_T *, char_u *, size_t));
227 +void gdb_docmd __ARGS((gdb_handle_T *, char_u *));
228 +void gdb_setwinput __ARGS((gdb_handle_T *, char_u *));
229 +int gdb_iswinput __ARGS((gdb_handle_T *));
230 +void gdb_winput __ARGS((gdb_handle_T *));
231 +long gdb_process_output __ARGS((gdb_handle_T *, long, void *));
232 +win_T *gdb_window __ARGS((gdb_handle_T *));
233 +/* vim: set ft=c : */
235 Property changes on: src/quickfix.c
236 ___________________________________________________________________
237 Name: svn:keywords
238 + Id
240 Index: src/gui.c
241 ===================================================================
242 --- src/gui.c (.../vendor/vim/current) (revision 223)
243 +++ src/gui.c (.../trunk/vim) (revision 223)
244 @@ -2647,6 +2647,10 @@
245 long wtime;
247 int retval;
248 +#if defined(FEAT_GDB) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
249 + struct timeval start_tv;
250 + gettimeofday(&start_tv, NULL);
251 +#endif
254 * If we're going to wait a bit, update the menus and mouse shape for the
255 @@ -2673,7 +2677,35 @@
256 /* Blink when waiting for a character. Probably only does something
257 * for showmatch() */
258 gui_mch_start_blink();
260 +#ifdef FEAT_GDB
261 + while ((retval = gui_mch_wait_for_chars(wtime)) == FAIL)
263 + if (gdb_event(gdb) && gdb_allowed(gdb))
265 + gui_mch_stop_blink(); // cursor off while drawing status line
266 +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
267 + if ((wtime = gdb_process_output(gdb, wtime, (void *)&start_tv)) < 0)
268 +# else
269 + /* guess we got interrupted halfway */
270 + wtime = wtime / 2;
272 + if ((wtime = gdb_process_output(gdb, wtime, NULL)) < 0)
273 +# endif
275 + return 0; /* launch input-line window */
277 + gui_mch_start_blink();
279 + if (wtime == 0L)
280 + break;
282 + else
283 + break;
285 +#else
286 retval = gui_mch_wait_for_chars(wtime);
287 +#endif
288 gui_mch_stop_blink();
289 return retval;
291 @@ -2689,7 +2721,27 @@
292 * 'updatetime' and if nothing is typed within that time put the
293 * K_CURSORHOLD key in the input buffer.
295 +# ifdef FEAT_GDB
296 + for (;;)
298 + retval = gui_mch_wait_for_chars(p_ut);
299 + if (retval == FAIL && gdb_event(gdb) && gdb_allowed(gdb))
301 + gui_mch_stop_blink(); // cursor off while drawing status line
302 + if (gdb_process_output(gdb, -1L, NULL) < 0)
304 + return 0; /* launch input-line window */
306 + gui_mch_start_blink();
308 + else
309 + break;
312 + if (retval == OK)
313 +# else
314 if (gui_mch_wait_for_chars(p_ut) == OK)
315 +# endif
316 retval = OK;
317 #ifdef FEAT_AUTOCMD
318 else if (trigger_cursorhold())
319 @@ -2710,7 +2762,25 @@
321 /* Blocking wait. */
322 before_blocking();
323 +#ifdef FEAT_GDB
324 + for (;;)
326 + retval = gui_mch_wait_for_chars(-1L);
327 + if (retval == FAIL && gdb_event(gdb) && gdb_allowed(gdb))
329 + gui_mch_stop_blink(); // cursor off while drawing status line
330 + if (gdb_process_output(gdb, -1L, NULL) < 0)
332 + return 0; /* launch input-line window */
334 + gui_mch_start_blink();
336 + else
337 + break;
339 +#else
340 retval = gui_mch_wait_for_chars(-1L);
341 +#endif
344 gui_mch_stop_blink();
346 Property changes on: src/gui.c
347 ___________________________________________________________________
348 Name: svn:keywords
349 + Id
352 Property changes on: src/macros.h
353 ___________________________________________________________________
354 Name: svn:keywords
355 + Id
358 Property changes on: src/gui.h
359 ___________________________________________________________________
360 Name: svn:keywords
361 + Id
364 Property changes on: src/regexp.c
365 ___________________________________________________________________
366 Name: svn:keywords
367 + Id
370 Property changes on: src/regexp.h
371 ___________________________________________________________________
372 Name: svn:keywords
373 + Id
375 Index: src/config.mk.in
376 ===================================================================
377 --- src/config.mk.in (.../vendor/vim/current) (revision 223)
378 +++ src/config.mk.in (.../trunk/vim) (revision 223)
379 @@ -71,6 +71,9 @@
380 WORKSHOP_SRC = @WORKSHOP_SRC@
381 WORKSHOP_OBJ = @WORKSHOP_OBJ@
383 +GDB_SRC = @GDB_SRC@
384 +GDB_OBJ = @GDB_OBJ@
386 NETBEANS_SRC = @NETBEANS_SRC@
387 NETBEANS_OBJ = @NETBEANS_OBJ@
390 Property changes on: src/vim.h
391 ___________________________________________________________________
392 Name: svn:keywords
393 + Id
396 Property changes on: src/gui_at_fs.c
397 ___________________________________________________________________
398 Name: svn:keywords
399 + Id
402 Property changes on: src/gui_athena.c
403 ___________________________________________________________________
404 Name: svn:keywords
405 + Id
407 Index: src/structs.h
408 ===================================================================
409 --- src/structs.h (.../vendor/vim/current) (revision 223)
410 +++ src/structs.h (.../trunk/vim) (revision 223)
411 @@ -577,7 +577,7 @@
412 linenr_T lnum; /* line number which has this sign */
413 int typenr; /* typenr of sign */
414 signlist_T *next; /* next signlist entry */
415 -# ifdef FEAT_NETBEANS_INTG
416 +# if defined(FEAT_NETBEANS_INTG) || defined(FEAT_GDB)
417 signlist_T *prev; /* previous entry -- for easy reordering */
418 # endif
420 @@ -589,6 +589,13 @@
421 #define SIGN_TEXT 3
422 #endif
424 +#ifdef FEAT_GDB
425 +typedef struct
427 + int dummy;
428 +} gdb_handle_T;
429 +#endif
432 * Argument list: Array of file names.
433 * Used for the global argument list and the argument lists local to a window.
435 Property changes on: src/structs.h
436 ___________________________________________________________________
437 Name: svn:keywords
438 + Id
441 Property changes on: src/ui.c
442 ___________________________________________________________________
443 Name: svn:keywords
444 + Id
447 Property changes on: src/getchar.c
448 ___________________________________________________________________
449 Name: svn:keywords
450 + Id
453 Property changes on: src/memfile.c
454 ___________________________________________________________________
455 Name: svn:keywords
456 + Id
459 Property changes on: src/xxd
460 ___________________________________________________________________
461 Name: svn:ignore
462 + xxd
465 Index: src/feature.h
466 ===================================================================
467 --- src/feature.h (.../vendor/vim/current) (revision 223)
468 +++ src/feature.h (.../trunk/vim) (revision 223)
469 @@ -1210,6 +1210,24 @@
470 #endif
473 + * +gdb Gdb interface. Must be included through configure,
474 + * see Makefile and uncomment "--enable-gdb"
475 + * Not included when required features are missing
476 + * and use explicitly the following FEAT_NORMAL features:
477 + * FEAT_CMDWIN FEAT_EVAL FEAT_STL_OPT FEAT_MODIFY_FNAME
478 + * FEAT_SEARCHPATH FEAT_WINDOWS FEAT_QUICKFIX
479 + */
480 +#ifdef FEAT_GDB
481 +# if !defined(FEAT_NORMAL) || !defined(HAVE_SYS_WAIT_H) || !defined(HAVE_FCNTL_H)
482 +# undef FEAT_GDB
483 +# else
484 +# ifndef FEAT_SIGNS
485 +# define FEAT_SIGNS /* include +signs */
486 +# endif
487 +# endif
488 +#endif
491 * +balloon_eval Allow balloon expression evaluation. Used with a
492 * debugger and for tooltips.
493 * Only for GUIs where it was implemented.
495 Property changes on: src/feature.h
496 ___________________________________________________________________
497 Name: svn:keywords
498 + Id
501 Property changes on: src/undo.c
502 ___________________________________________________________________
503 Name: svn:keywords
504 + Id
506 Index: src/buffer.c
507 ===================================================================
508 --- src/buffer.c (.../vendor/vim/current) (revision 223)
509 +++ src/buffer.c (.../trunk/vim) (revision 223)
510 @@ -613,6 +613,9 @@
511 #ifdef FEAT_AUTOCMD
512 aubuflocal_remove(buf);
513 #endif
514 +#ifdef FEAT_GDB
515 + gdb_buffer_free(gdb, buf);
516 +#endif
517 vim_free(buf);
520 @@ -5093,7 +5096,7 @@
521 newsign->lnum = lnum;
522 newsign->typenr = typenr;
523 newsign->next = next;
524 -#ifdef FEAT_NETBEANS_INTG
525 +#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_GDB)
526 newsign->prev = prev;
527 if (next != NULL)
528 next->prev = newsign;
529 @@ -5139,12 +5142,12 @@
530 return;
532 else if (
533 -#ifndef FEAT_NETBEANS_INTG /* keep signs sorted by lnum */
534 +#if !defined(FEAT_NETBEANS_INTG) && !defined(FEAT_GDB) /* keep signs sorted by lnum */
535 id < 0 &&
536 #endif
537 lnum < sign->lnum)
539 -#ifdef FEAT_NETBEANS_INTG /* insert new sign at head of list for this lnum */
540 +#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_GDB) /* insert new sign at head of list for this lnum */
541 /* XXX - GRP: Is this because of sign slide problem? Or is it
542 * really needed? Or is it because we allow multiple signs per
543 * line? If so, should I add that feature to FEAT_SIGNS?
544 @@ -5161,7 +5164,7 @@
546 prev = sign;
548 -#ifdef FEAT_NETBEANS_INTG /* insert new sign at head of list for this lnum */
549 +#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_GDB) /* insert new sign at head of list for this lnum */
550 /* XXX - GRP: See previous comment */
551 while (prev != NULL && prev->lnum == lnum)
552 prev = prev->prev;
553 @@ -5237,7 +5240,7 @@
554 if (sign->id == id)
556 *lastp = next;
557 -#ifdef FEAT_NETBEANS_INTG
558 +#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_GDB)
559 if (next != NULL)
560 next->prev = sign->prev;
561 #endif
562 @@ -5417,12 +5420,41 @@
563 long amount_after;
565 signlist_T *sign; /* a sign in a b_signlist */
566 +# ifdef FEAT_GDB
567 + int lnum;
569 for (sign = curbuf->b_signlist; sign != NULL; sign = sign->next)
571 + lnum = sign->lnum;
573 if (sign->lnum >= line1 && sign->lnum <= line2)
575 if (amount == MAXLNUM)
576 + lnum = line1;
577 + else
578 + lnum += amount;
580 + else if (sign->lnum > line2)
581 + lnum += amount_after;
583 + /* Keep sign->lnum unchanged, but mark as changed the sign line and
584 + * the new line position if we had moved the line
585 + * (otherwise their highlighting may be scrolled along) */
586 + if (gdb_isrunning(gdb) && lnum != sign->lnum)
588 + changed_lines(sign->lnum, 0, sign->lnum + 1, 0);
589 + changed_lines(lnum, 0, lnum + 1, 0);
591 + else
592 + sign->lnum = lnum;
594 +# else
596 + for (sign = curbuf->b_signlist; sign != NULL; sign = sign->next)
598 + if (sign->lnum >= line1 && sign->lnum <= line2)
600 + if (amount == MAXLNUM)
601 sign->lnum = line1;
602 else
603 sign->lnum += amount;
604 @@ -5430,6 +5462,7 @@
605 else if (sign->lnum > line2)
606 sign->lnum += amount_after;
608 +# endif
610 #endif /* FEAT_SIGNS */
613 Property changes on: src/buffer.c
614 ___________________________________________________________________
615 Name: svn:keywords
616 + Id
618 Index: src/pty.c
619 ===================================================================
620 --- src/pty.c (.../vendor/vim/current) (revision 223)
621 +++ src/pty.c (.../trunk/vim) (revision 223)
622 @@ -37,7 +37,7 @@
623 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
626 -/* RCS_ID("$Id: pty.c,v 1.1 2004/06/13 20:04:27 vimboss Exp $ FAU") */
627 +/* RCS_ID("$Id$ FAU") */
629 #include "vim.h"
632 Property changes on: src/pty.c
633 ___________________________________________________________________
634 Name: svn:keywords
635 + Id
638 Property changes on: src/misc1.c
639 ___________________________________________________________________
640 Name: svn:keywords
641 + Id
643 Index: src/main.c
644 ===================================================================
645 --- src/main.c (.../vendor/vim/current) (revision 223)
646 +++ src/main.c (.../trunk/vim) (revision 223)
647 @@ -198,6 +198,10 @@
648 vim_tcl_init(params.argv[0]);
649 #endif
651 +#ifdef FEAT_GDB
652 + gdb = gdb_new();
653 +#endif
655 #ifdef MEM_PROFILE
656 atexit(vim_mem_profile_dump);
657 #endif
658 @@ -1275,6 +1279,11 @@
659 apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
660 #endif
662 +#ifdef FEAT_GDB
663 + /* Before viminfo stuff to wipeout gdb buffer and remove from list */
664 + gdb_delete(&gdb);
665 +#endif
667 #ifdef FEAT_VIMINFO
668 if (*p_viminfo != NUL)
669 /* Write out the registers, history, marks etc, to the viminfo file */
671 Property changes on: src/main.c
672 ___________________________________________________________________
673 Name: svn:keywords
674 + Id
677 Property changes on: src/edit.c
678 ___________________________________________________________________
679 Name: svn:keywords
680 + Id
683 Property changes on: src/syntax.c
684 ___________________________________________________________________
685 Name: svn:keywords
686 + Id
688 Index: src/eval.c
689 ===================================================================
690 --- src/eval.c (.../vendor/vim/current) (revision 223)
691 +++ src/eval.c (.../trunk/vim) (revision 223)
692 @@ -540,6 +540,9 @@
693 static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
694 static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
695 static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
696 +#ifdef FEAT_GDB
697 +static void f_gdb __ARGS((typval_T *argvars, typval_T *rettv));
698 +#endif
699 static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
700 static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
701 static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
702 @@ -7499,6 +7502,9 @@
703 {"foreground", 0, 0, f_foreground},
704 {"function", 1, 1, f_function},
705 {"garbagecollect", 0, 1, f_garbagecollect},
706 +#ifdef FEAT_GDB
707 + {"gdb", 1, 1, f_gdb},
708 +#endif
709 {"get", 2, 3, f_get},
710 {"getbufline", 2, 3, f_getbufline},
711 {"getbufvar", 2, 2, f_getbufvar},
712 @@ -10326,7 +10332,26 @@
713 garbage_collect_at_exit = TRUE;
716 +#ifdef FEAT_GDB
718 + * "gdb()" function
719 + */
720 + static void
721 +f_gdb(argvars, rettv)
722 + typval_T *argvars;
723 + typval_T *rettv;
725 + char_u *cmd = get_tv_string(&argvars[0]);
727 + if (*cmd == NUL)
728 + gdb_setwinput(gdb, (char_u *)""); /* open the window input-line */
729 + else
730 + gdb_docmd(gdb, cmd); /* send cmd to gdb */
731 + rettv->vval.v_number = 1;
733 +#endif
736 * "get()" function
738 static void
739 @@ -11479,6 +11504,9 @@
740 #if !defined(USE_SYSTEM) && defined(UNIX)
741 "fork",
742 #endif
743 +#ifdef FEAT_GDB
744 + "gdb",
745 +#endif
746 #ifdef FEAT_GETTEXT
747 "gettext",
748 #endif
750 Property changes on: src/eval.c
751 ___________________________________________________________________
752 Name: svn:keywords
753 + Id
755 Index: src/normal.c
756 ===================================================================
757 --- src/normal.c (.../vendor/vim/current) (revision 223)
758 +++ src/normal.c (.../trunk/vim) (revision 223)
759 @@ -637,9 +637,23 @@
760 dont_scroll = FALSE; /* allow scrolling here */
761 #endif
763 +#if defined(FEAT_GDB) && defined(FEAT_CMDWIN)
764 + /* Launch the input-line window */
765 + if (cmdwin_type == 0 && gdb_iswinput(gdb))
767 + gdb_winput(gdb);
768 + goto normal_end;
770 +#endif
773 * Get the command character from the user.
775 +#ifdef FEAT_GDB
776 + if (toplevel)
777 + c = gdb_safe_vgetc(gdb);
778 + else
779 +#endif
780 c = safe_vgetc();
782 #ifdef FEAT_LANGMAP
783 @@ -725,6 +739,11 @@
784 ++allow_keys; /* no mapping for nchar, but keys */
786 ++no_zero_mapping; /* don't map zero here */
787 +#ifdef FEAT_GDB
788 + if (toplevel)
789 + c = gdb_safe_vgetc(gdb);
790 + else
791 +#endif
792 c = plain_vgetc();
793 #ifdef FEAT_LANGMAP
794 LANGMAP_ADJUST(c, TRUE);
795 @@ -750,6 +769,11 @@
796 ca.count0 = 0;
797 ++no_mapping;
798 ++allow_keys; /* no mapping for nchar, but keys */
799 +#ifdef FEAT_GDB
800 + if (toplevel)
801 + c = gdb_safe_vgetc(gdb);
802 + else
803 +#endif
804 c = plain_vgetc(); /* get next character */
805 #ifdef FEAT_LANGMAP
806 LANGMAP_ADJUST(c, TRUE);
807 @@ -940,6 +964,11 @@
808 * For 'g' get the next character now, so that we can check for
809 * "gr", "g'" and "g`".
811 +#ifdef FEAT_GDB
812 + if (toplevel)
813 + ca.nchar = gdb_safe_vgetc(gdb);
814 + else
815 +#endif
816 ca.nchar = plain_vgetc();
817 #ifdef FEAT_LANGMAP
818 LANGMAP_ADJUST(ca.nchar, TRUE);
819 @@ -997,6 +1026,11 @@
820 im_set_active(TRUE);
821 #endif
823 +#ifdef FEAT_GDB
824 + if (toplevel)
825 + *cp = gdb_safe_vgetc(gdb);
826 + else
827 +#endif
828 *cp = plain_vgetc();
830 if (langmap_active)
831 @@ -1104,6 +1138,11 @@
832 while (enc_utf8 && lang && (c = vpeekc()) > 0
833 && (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1))
835 +#ifdef FEAT_GDB
836 + if (toplevel)
837 + c = gdb_safe_vgetc(gdb);
838 + else
839 +#endif
840 c = plain_vgetc();
841 if (!utf_iscomposing(c))
843 @@ -8668,6 +8707,10 @@
844 && cap->opcount == 0
845 && cap->count0 == 0
846 && cap->oap->regname == 0
847 +#ifdef FEAT_GDB
848 + /* don't beep when opening gdb input-line window */
849 + && !gdb_iswinput(gdb)
850 +#endif
851 && !p_im);
853 if (cap->arg) /* TRUE for CTRL-C */
855 Property changes on: src/normal.c
856 ___________________________________________________________________
857 Name: svn:keywords
858 + Id
861 Property changes on: src/gui_gtk.c
862 ___________________________________________________________________
863 Name: svn:keywords
864 + Id
867 Property changes on: src/if_cscope.c
868 ___________________________________________________________________
869 Name: svn:keywords
870 + Id
873 Property changes on: src/gui_beval.c
874 ___________________________________________________________________
875 Name: svn:keywords
876 + Id
879 Property changes on: src/if_ruby.c
880 ___________________________________________________________________
881 Name: svn:keywords
882 + Id
885 Property changes on: src/if_cscope.h
886 ___________________________________________________________________
887 Name: svn:keywords
888 + Id
891 Property changes on: src/if_python.c
892 ___________________________________________________________________
893 Name: svn:keywords
894 + Id
897 Property changes on: src/gui_beval.h
898 ___________________________________________________________________
899 Name: svn:keywords
900 + Id
902 Index: src/proto.h
903 ===================================================================
904 --- src/proto.h (.../vendor/vim/current) (revision 223)
905 +++ src/proto.h (.../trunk/vim) (revision 223)
906 @@ -238,6 +238,10 @@
907 # include "if_xcmdsrv.pro"
908 # endif
910 +# ifdef FEAT_GDB
911 +# include "gdb.pro"
912 +# endif
915 * The perl include files pollute the namespace, therefore proto.h must be
916 * included before the perl include files. But then CV is not defined, which
918 Property changes on: src/proto.h
919 ___________________________________________________________________
920 Name: svn:keywords
921 + Id
924 Property changes on: src/gui_motif.c
925 ___________________________________________________________________
926 Name: svn:keywords
927 + Id
930 Property changes on: src/charset.c
931 ___________________________________________________________________
932 Name: svn:keywords
933 + Id
935 Index: src/Makefile
936 ===================================================================
937 --- src/Makefile (.../vendor/vim/current) (revision 223)
938 +++ src/Makefile (.../trunk/vim) (revision 223)
939 @@ -412,6 +412,9 @@
940 # WORKSHOP - Sun Visual Workshop interface. Only works with Motif!
941 #CONF_OPT_WORKSHOP = --enable-workshop
943 +# GDB - Include support for gdb
944 +CONF_OPT_GDB = --enable-gdb
946 # NETBEANS - NetBeans interface. Only works with Motif, GTK, and gnome.
947 # Motif version must have XPM libraries (see |workshop-xpm|).
948 # Uncomment this when you do not want the netbeans interface.
949 @@ -1414,12 +1417,14 @@
951 SRC = $(BASIC_SRC) $(GUI_SRC) $(HANGULIN_SRC) $(MZSCHEME_SRC) \
952 $(PERL_SRC) $(PYTHON_SRC) $(TCL_SRC) $(RUBY_SRC) \
953 + $(GDB_SRC) \
954 $(SNIFF_SRC) $(WORKSHOP_SRC) $(WSDEBUG_SRC)
956 TAGS_SRC = *.c *.cpp if_perl.xs
958 EXTRA_SRC = hangulin.c if_mzsch.c auto/if_perl.c if_perlsfio.c \
959 if_python.c if_tcl.c if_ruby.c if_sniff.c gui_beval.c \
960 + gdb.c clewn/gdb_lvl2.c clewn/gdb_lvl3.c clewn/misc.c clewn/obstack.c \
961 workshop.c wsdebug.c integration.c netbeans.c
963 # All sources, also the ones that are not configured
964 @@ -1429,6 +1434,7 @@
965 # checks more, but may not work well for checking a GUI that wasn't configured.
966 # The perl sources also don't work well with lint.
967 LINT_SRC = $(BASIC_SRC) $(GUI_SRC) $(HANGULIN_SRC) $(PYTHON_SRC) $(TCL_SRC) \
968 + $(GDB_SRC) \
969 $(SNIFF_SRC) $(WORKSHOP_SRC) $(WSDEBUG_SRC) $(NETBEANS_SRC)
970 #LINT_SRC = $(SRC)
971 #LINT_SRC = $(ALL_SRC)
972 @@ -1489,6 +1495,7 @@
973 $(RUBY_OBJ) \
974 $(OS_EXTRA_OBJ) \
975 $(WORKSHOP_OBJ) \
976 + $(GDB_OBJ) \
977 $(NETBEANS_OBJ) \
978 $(WSDEBUG_OBJ)
980 @@ -1544,6 +1551,7 @@
981 window.pro \
982 gui_beval.pro \
983 workshop.pro \
984 + gdb.pro \
985 netbeans.pro \
986 $(ALL_GUI_PRO) \
987 $(TCL_PRO)
988 @@ -1577,6 +1585,7 @@
989 $(CONF_OPT_TCL) $(CONF_OPT_RUBY) $(CONF_OPT_NLS) \
990 $(CONF_OPT_CSCOPE) $(CONF_OPT_MULTIBYTE) $(CONF_OPT_INPUT) \
991 $(CONF_OPT_OUTPUT) $(CONF_OPT_GPM) $(CONF_OPT_WORKSHOP) \
992 + $(CONF_OPT_GDB) \
993 $(CONF_OPT_SNIFF) $(CONF_OPT_FEAT) $(CONF_TERM_LIB) \
994 $(CONF_OPT_COMPBY) $(CONF_OPT_ACL) $(CONF_OPT_NETBEANS) \
995 $(CONF_ARGS) $(CONF_OPT_MZSCHEME) $(CONF_OPT_PLTHOME) \
996 @@ -2552,6 +2561,21 @@
997 objects/workshop.o: workshop.c
998 $(CCC) -o $@ workshop.c
1000 +objects/gdb.o: gdb.c
1001 + $(CCC) -o $@ gdb.c
1003 +objects/gdb_lvl2.o: clewn/gdb_lvl2.c
1004 + $(CCC) -o $@ clewn/gdb_lvl2.c
1006 +objects/gdb_lvl3.o: clewn/gdb_lvl3.c
1007 + $(CCC) -o $@ clewn/gdb_lvl3.c
1009 +objects/misc.o: clewn/misc.c
1010 + $(CCC) -o $@ clewn/misc.c
1012 +objects/obstack.o: clewn/obstack.c
1013 + $(CCC) -o $@ clewn/obstack.c
1015 objects/wsdebug.o: wsdebug.c
1016 $(CCC) -o $@ wsdebug.c
1018 @@ -2948,6 +2972,13 @@
1019 os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h \
1020 structs.h regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h \
1021 proto.h globals.h farsi.h arabic.h version.h workshop.h
1022 +objects/gdb.o: gdb.c clewn/gdb.h clewn/misc.h auto/config.h vim.h feature.h
1023 +objects/gdb_lvl2.o: clewn/misc.h clewn/gdb_lvl2.c clewn/gdb_lvl3.c \
1024 + gdb.c clewn/gdb.h auto/config.h vim.h feature.h
1025 +objects/gdb_lvl3.o: clewn/misc.h clewn/gdb_lvl3.c gdb.c clewn/gdb.h\
1026 + auto/config.h vim.h feature.h
1027 +objects/misc.o: clewn/misc.c clewn/misc.h
1028 +objects/obstack.o: clewn/obstack.c clewn/obstack.h
1029 objects/wsdebug.o: wsdebug.c
1030 objects/integration.o: integration.c vim.h auto/config.h feature.h os_unix.h \
1031 auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
1033 Property changes on: src/if_tcl.c
1034 ___________________________________________________________________
1035 Name: svn:keywords
1036 + Id
1039 Property changes on: src/wsdebug.c
1040 ___________________________________________________________________
1041 Name: svn:keywords
1042 + Id
1045 Property changes on: src/wsdebug.h
1046 ___________________________________________________________________
1047 Name: svn:keywords
1048 + Id
1051 Property changes on: src/nbdebug.c
1052 ___________________________________________________________________
1053 Name: svn:keywords
1054 + Id
1057 Property changes on: src/diff.c
1058 ___________________________________________________________________
1059 Name: svn:keywords
1060 + Id
1063 Property changes on: src/tag.c
1064 ___________________________________________________________________
1065 Name: svn:keywords
1066 + Id
1069 Property changes on: src/nbdebug.h
1070 ___________________________________________________________________
1071 Name: svn:keywords
1072 + Id
1075 Property changes on: src/misc2.c
1076 ___________________________________________________________________
1077 Name: svn:keywords
1078 + Id
1080 Index: src/config.h.in
1081 ===================================================================
1082 --- src/config.h.in (.../vendor/vim/current) (revision 223)
1083 +++ src/config.h.in (.../trunk/vim) (revision 223)
1084 @@ -367,6 +367,9 @@
1085 /* Define if you want to include Sun Visual Workshop support. */
1086 #undef FEAT_SUN_WORKSHOP
1088 +/* Define if you want to include GDB support. */
1089 +#undef FEAT_GDB
1091 /* Define if you want to include NetBeans integration. */
1092 #undef FEAT_NETBEANS_INTG
1095 Property changes on: src/mbyte.c
1096 ___________________________________________________________________
1097 Name: svn:keywords
1098 + Id
1100 Index: src/gui_gtk_x11.c
1101 ===================================================================
1102 --- src/gui_gtk_x11.c (.../vendor/vim/current) (revision 223)
1103 +++ src/gui_gtk_x11.c (.../trunk/vim) (revision 223)
1104 @@ -6381,7 +6381,13 @@
1105 gui_mch_update(void)
1107 while (gtk_events_pending() && !vim_is_input_buf_full())
1109 +#ifdef FEAT_GDB
1110 + if (gdb_event(gdb)) /* got a gdb event */
1111 + return;
1112 +#endif
1113 gtk_main_iteration_do(FALSE);
1117 static gint
1118 @@ -6418,7 +6424,25 @@
1120 #endif
1122 +#ifdef FEAT_GDB
1124 + * Callback function, used when data is available on the gdb file descriptor.
1125 + */
1126 +/* ARGSUSED */
1127 + static void
1128 +gdb_request_cb(
1129 + gpointer data,
1130 + gint source_fd,
1131 + GdkInputCondition condition)
1133 + gdb_set_event(gdb, TRUE);
1135 + if (gtk_main_level() > 0)
1136 + gtk_main_quit();
1138 +#endif
1141 * GUI input routine called by gui_wait_for_chars(). Waits for a character
1142 * from the keyboard.
1143 * wtime == -1 Wait forever.
1144 @@ -6437,6 +6461,10 @@
1145 static int sniff_on = 0;
1146 static gint sniff_input_id = 0;
1147 #endif
1148 +#ifdef FEAT_GDB
1149 + static int gdb_on = 0;
1150 + static gint gdb_input_id = 0;
1151 +#endif
1153 #ifdef FEAT_SNIFF
1154 if (sniff_on && !want_sniff_request)
1155 @@ -6454,6 +6482,25 @@
1157 #endif
1159 +#ifdef FEAT_GDB
1160 + /* Remove call back for previous gdb connection */
1161 + if (! gdb_allowed(gdb) && gdb_on)
1163 + if (gdb_input_id)
1164 + gdk_input_remove(gdb_input_id);
1165 + gdb_on = 0;
1168 + /* A new gdb connection */
1169 + if (gdb_allowed(gdb) && !gdb_on)
1171 + /* Add gdb file descriptor to watch for available data in main loop. */
1172 + gdb_input_id = gdk_input_add(gdb_fd(gdb),
1173 + GDK_INPUT_READ, gdb_request_cb, NULL);
1174 + gdb_on = 1;
1176 +#endif
1178 timed_out = FALSE;
1180 /* this timeout makes sure that we will return if no characters arrived in
1181 @@ -6498,6 +6545,15 @@
1182 gtk_timeout_remove(timer);
1183 return OK;
1186 +#ifdef FEAT_GDB
1187 + if (wtime != 0L && gdb_allowed(gdb) && gdb_event(gdb))
1189 + if (timer != 0 && !timed_out)
1190 + gtk_timeout_remove(timer);
1191 + return FAIL;
1193 +#endif
1194 } while (wtime < 0 || !timed_out);
1198 Property changes on: src/gui_gtk_x11.c
1199 ___________________________________________________________________
1200 Name: svn:keywords
1201 + Id
1203 Index: src/os_unix.c
1204 ===================================================================
1205 --- src/os_unix.c (.../vendor/vim/current) (revision 223)
1206 +++ src/os_unix.c (.../trunk/vim) (revision 223)
1207 @@ -183,6 +183,9 @@
1208 static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
1209 static int sig_alarm_called;
1210 #endif
1211 +#if defined(FEAT_GDB) && defined(SIGCHLD)
1212 +static RETSIGTYPE gdb_catch_sigchld __ARGS(SIGPROTOARG);
1213 +#endif
1214 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
1216 static void catch_int_signal __ARGS((void));
1217 @@ -312,6 +315,9 @@
1218 #ifdef SIGPIPE
1219 {SIGPIPE, "PIPE", FALSE},
1220 #endif
1221 +#if defined(FEAT_GDB) && defined(SIGCHLD)
1222 + {SIGCHLD, "CHLD", FALSE},
1223 +#endif
1224 {-1, "Unknown!", FALSE}
1227 @@ -341,6 +347,10 @@
1228 int tb_change_cnt;
1230 int len;
1231 +#if defined(FEAT_GDB) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1232 + struct timeval start_tv;
1233 + gettimeofday(&start_tv, NULL);
1234 +#endif
1236 /* Check if window changed size while we were busy, perhaps the ":set
1237 * columns=99" command was used. */
1238 @@ -351,6 +361,21 @@
1240 while (WaitForChar(wtime) == 0) /* no character available */
1242 +#ifdef FEAT_GDB
1243 + if (gdb_event(gdb) && gdb_allowed(gdb))
1245 +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1246 + if ((wtime = gdb_process_output(gdb, wtime, (void *)&start_tv)) < 0)
1247 +# else
1248 + /* guess we got interrupted halfway */
1249 + wtime = wtime / 2;
1251 + if ((wtime = gdb_process_output(gdb, wtime, NULL)) < 0)
1252 +# endif
1253 + return 0; /* launch input-line window */
1254 + continue;
1256 +#endif
1257 if (!do_resize) /* return if not interrupted by resize */
1258 return 0;
1259 handle_resize();
1260 @@ -363,8 +388,25 @@
1261 * flush all the swap files to disk.
1262 * Also done when interrupted by SIGWINCH.
1264 +#ifdef FEAT_GDB
1266 + wtime = p_ut;
1267 + while (WaitForChar(wtime) == 0)
1269 + if (gdb_event(gdb) && gdb_allowed(gdb))
1271 +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1272 + if ((wtime = gdb_process_output(gdb, wtime, (void *)&start_tv)) < 0)
1273 +# else
1274 + if ((wtime = gdb_process_output(gdb, wtime, NULL)) < 0)
1275 +# endif
1276 + return 0; /* launch input-line window */
1277 + continue;
1279 +#else
1280 if (WaitForChar(p_ut) == 0)
1282 +#endif
1283 #ifdef FEAT_AUTOCMD
1284 if (trigger_cursorhold() && maxlen >= 3
1285 && !typebuf_changed(tb_change_cnt))
1286 @@ -376,6 +418,10 @@
1288 #endif
1289 before_blocking();
1290 +#ifdef FEAT_GDB
1291 + break;
1292 + } /* while (WaitForChar(wtime) == 0) */
1293 +#endif
1297 @@ -387,6 +433,16 @@
1298 * we want to be interrupted by the winch signal
1300 WaitForChar(-1L);
1302 +#ifdef FEAT_GDB
1303 + if (gdb_event(gdb) && gdb_allowed(gdb))
1305 + if (gdb_process_output(gdb, -1L, NULL) < 0)
1306 + return 0; /* launch input-line window */
1307 + continue;
1309 +#endif
1311 if (do_resize) /* interrupted by SIGWINCH signal */
1312 continue;
1314 @@ -858,6 +914,30 @@
1316 #endif
1318 +#if defined(FEAT_GDB) && defined(SIGCHLD)
1320 + * On SIGCHLD, note when gdb process is defunct or does not exist any more
1321 + */
1322 + static RETSIGTYPE
1323 +gdb_catch_sigchld SIGDEFARG(sigarg)
1325 + pid_t wait_pid;
1326 + pid_t pid;
1328 + if (sigarg == SIGCHLD && (pid = gdb_pid(gdb)) != -1)
1330 + wait_pid = waitpid(pid, NULL, WNOHANG);
1332 + if ((wait_pid == (pid_t)-1 && errno == ECHILD)
1333 + || wait_pid == pid)
1334 + gdb_set_sigchld(gdb, TRUE);
1337 + signal(SIGCHLD, (RETSIGTYPE (*)())gdb_catch_sigchld);
1338 + SIGRETURN;
1340 +#endif
1342 #if (defined(HAVE_SETJMP_H) \
1343 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
1344 || defined(FEAT_LIBCALL))) \
1345 @@ -1203,6 +1283,13 @@
1346 #endif
1349 + * Catch SIGCHLD to monitor gdb process state
1350 + */
1351 +#if defined(FEAT_GDB) && defined(SIGCHLD)
1352 + signal(SIGCHLD, (RETSIGTYPE (*)())gdb_catch_sigchld);
1353 +#endif
1355 + /*
1356 * Arrange for other signals to gracefully shutdown Vim.
1358 catch_signals(deathtrap, SIG_ERR);
1359 @@ -4733,7 +4820,12 @@
1360 # endif
1361 #endif
1362 #ifndef HAVE_SELECT
1363 +# ifdef FEAT_GDB
1364 + struct pollfd fds[6];
1365 + int gdb_idx = -1;
1366 +# else
1367 struct pollfd fds[5];
1368 +# endif
1369 int nfd;
1370 # ifdef FEAT_XCLIPBOARD
1371 int xterm_idx = -1;
1372 @@ -4794,7 +4886,23 @@
1373 nfd++;
1375 # endif
1376 +# ifdef FEAT_GDB
1377 + if (msec != 0L && gdb_allowed(gdb))
1379 + /* handle pending SIGCHLD from gdb */
1380 + if (gdb_sigchld(gdb))
1382 + gdb_set_event(gdb, TRUE);
1383 + return 0;
1386 + gdb_idx = nfd;
1387 + fds[nfd].fd = gdb_fd(gdb);
1388 + fds[nfd].events = POLLIN;
1389 + nfd++;
1391 +# endif
1393 ret = poll(fds, nfd, towait);
1394 # ifdef FEAT_MZSCHEME
1395 if (ret == 0 && mzquantum_used)
1396 @@ -4802,6 +4910,27 @@
1397 finished = FALSE;
1398 # endif
1400 +# ifdef FEAT_GDB
1401 + if (msec != 0L && gdb_allowed(gdb))
1403 + if (ret > 0 && fds[gdb_idx].revents & POLLIN)
1405 + ret--;
1406 + if (!got_int)
1407 + gdb_set_event(gdb, TRUE);
1408 + else
1409 + gdb_set_event(gdb, FALSE);
1412 + /* EINTR poll error */
1413 + if (ret < 0 && gdb_sigchld(gdb) && !got_int)
1414 + gdb_set_event(gdb, TRUE);
1416 + /* an event: gdb's SIGCHLD or gdb data output */
1417 + if (gdb_event(gdb))
1418 + return 0;
1420 +# endif
1421 # ifdef FEAT_SNIFF
1422 if (ret < 0)
1423 sniff_disconnect(1);
1424 @@ -4928,7 +5057,24 @@
1425 maxfd = xsmp_icefd;
1427 # endif
1428 +# ifdef FEAT_GDB
1429 + if (msec != 0L && gdb_allowed(gdb))
1431 + int fd = gdb_fd(gdb);
1433 + /* handle pending SIGCHLD from gdb */
1434 + if (gdb_sigchld(gdb))
1436 + gdb_set_event(gdb, TRUE);
1437 + return 0;
1440 + FD_SET(fd, &rfds);
1441 + if (maxfd < fd)
1442 + maxfd = fd;
1444 +# endif
1446 # ifdef OLD_VMS
1447 /* Old VMS as v6.2 and older have broken select(). It waits more than
1448 * required. Should not be used */
1449 @@ -4950,6 +5096,27 @@
1450 finished = FALSE;
1451 # endif
1453 +# ifdef FEAT_GDB
1454 + if (msec != 0L && gdb_allowed(gdb))
1456 + if (ret > 0 && FD_ISSET(gdb_fd(gdb), &rfds))
1458 + ret--;
1459 + if (! got_int)
1460 + gdb_set_event(gdb, TRUE);
1461 + else
1462 + gdb_set_event(gdb, FALSE);
1465 + /* EINTR select error */
1466 + if (ret < 0 && gdb_sigchld(gdb) && ! got_int)
1467 + gdb_set_event(gdb, TRUE);
1469 + /* an event: gdb's SIGCHLD or gdb data output */
1470 + if (gdb_event(gdb))
1471 + return 0;
1473 +# endif
1474 # ifdef FEAT_SNIFF
1475 if (ret < 0 )
1476 sniff_disconnect(1);
1478 Property changes on: src/os_unix.c
1479 ___________________________________________________________________
1480 Name: svn:keywords
1481 + Id
1484 Property changes on: src/fold.c
1485 ___________________________________________________________________
1486 Name: svn:keywords
1487 + Id
1489 Index: src/version.c
1490 ===================================================================
1491 --- src/version.c (.../vendor/vim/current) (revision 223)
1492 +++ src/version.c (.../trunk/vim) (revision 223)
1493 @@ -236,6 +236,11 @@
1494 #if !defined(USE_SYSTEM) && defined(UNIX)
1495 "+fork()",
1496 #endif
1497 +#ifdef FEAT_GDB
1498 + "+gdb",
1499 +#else
1500 + "-gdb",
1501 +#endif
1502 #ifdef FEAT_GETTEXT
1503 # ifdef DYNAMIC_GETTEXT
1504 "+gettext/dyn",
1506 Property changes on: src/version.c
1507 ___________________________________________________________________
1508 Name: svn:keywords
1509 + Id
1512 Property changes on: src/os_unix.h
1513 ___________________________________________________________________
1514 Name: svn:keywords
1515 + Id
1518 Property changes on: src/version.h
1519 ___________________________________________________________________
1520 Name: svn:keywords
1521 + Id
1524 Property changes on: src/keymap.h
1525 ___________________________________________________________________
1526 Name: svn:keywords
1527 + Id
1529 Index: src/ex_getln.c
1530 ===================================================================
1531 --- src/ex_getln.c (.../vendor/vim/current) (revision 223)
1532 +++ src/ex_getln.c (.../trunk/vim) (revision 223)
1533 @@ -723,6 +723,12 @@
1534 #ifdef FEAT_CMDWIN
1535 if (c == cedit_key || c == K_CMDWIN)
1537 +#ifdef FEAT_GDB
1538 + /* Set cmdfirstc before calling ex_window (up to now it is NUL:
1539 + * the input line does not have a '@' leading character) */
1540 + if (firstc == '@')
1541 + ccline.cmdfirstc = firstc;
1542 +#endif
1544 * Open a window to edit the command line (and history).
1546 @@ -6011,6 +6017,30 @@
1547 /* don't use a new tab page */
1548 cmdmod.tab = 0;
1550 +# ifdef FEAT_GDB
1551 + /* Split below the displayed gdb window */
1552 + if (gdb_iswinput(gdb) && (wp = gdb_window(gdb)) != NULL
1553 + && (wp = wp->w_next) != NULL)
1555 + linenr_T topline;
1557 + curwin = wp;
1558 + curbuf = curwin->w_buffer;
1559 + topline = curwin->w_topline;
1561 + if (win_split((int)p_cwh, WSP_ABOVE) == FAIL)
1563 + curwin = old_curwin;
1564 + curbuf = old_curbuf;
1565 + beep_flush();
1566 + return K_IGNORE;
1569 + /* Do not scroll the window below gdb window */
1570 + set_topline(wp, topline + p_cwh + STATUS_HEIGHT);
1572 + else
1573 +# endif
1574 /* Create a window for the command-line buffer. */
1575 if (win_split((int)p_cwh, WSP_BOT) == FAIL)
1577 @@ -6057,6 +6087,20 @@
1578 set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL);
1581 +# ifdef FEAT_GDB
1582 + if (gdb_iswinput(gdb)) /* gdb window input-line */
1584 + add_map((char_u *)"<buffer> <C-Z> <C-Z><CR>", INSERT);
1585 + add_map((char_u *)"<buffer> <Tab> <C-Q><C-I><CR>", INSERT);
1586 + set_option_value((char_u *)"ft", 0L, (char_u *)"gdb", OPT_LOCAL);
1587 + set_option_value((char_u *)"fdc", 0L, NULL, OPT_LOCAL);
1589 + /* The window search-line does not have this: with a two lines history,
1590 + * the window shows an empty line at top */
1591 + curwin->w_valid = FALSE;
1593 +# endif
1595 /* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
1596 * sets 'textwidth' to 78). */
1597 curbuf->b_p_tw = 0;
1598 @@ -6180,6 +6224,10 @@
1599 cmdwin_result = Ctrl_C;
1600 else
1602 +#ifdef FEAT_GDB
1603 + if (ccline.cmdfirstc == '@')
1604 + ccline.cmdfirstc = NUL;
1605 +#endif
1606 ccline.cmdlen = (int)STRLEN(ccline.cmdbuff);
1607 ccline.cmdbufflen = ccline.cmdlen + 1;
1608 ccline.cmdpos = curwin->w_cursor.col;
1610 Property changes on: src/ex_getln.c
1611 ___________________________________________________________________
1612 Name: svn:keywords
1613 + Id
1615 Index: src/screen.c
1616 ===================================================================
1617 --- src/screen.c (.../vendor/vim/current) (revision 223)
1618 +++ src/screen.c (.../trunk/vim) (revision 223)
1619 @@ -5753,6 +5753,11 @@
1620 fillchar = fillchar_status(&attr, wp == curwin);
1622 get_trans_bufname(wp->w_buffer);
1623 +#ifdef FEAT_GDB
1624 + /* Replace fname with gdb window label */
1625 + gdb_label(gdb, wp->w_buffer, NameBuff, MAXPATHL);
1626 + trans_characters(NameBuff, MAXPATHL);
1627 +#endif
1628 p = NameBuff;
1629 len = (int)STRLEN(p);
1632 Property changes on: src/screen.c
1633 ___________________________________________________________________
1634 Name: svn:keywords
1635 + Id
1638 Property changes on: src/os_unixx.h
1639 ___________________________________________________________________
1640 Name: svn:keywords
1641 + Id
1644 Property changes on: src/arabic.c
1645 ___________________________________________________________________
1646 Name: svn:keywords
1647 + Id
1650 Property changes on: src/memline.c
1651 ___________________________________________________________________
1652 Name: svn:keywords
1653 + Id
1656 Property changes on: src/arabic.h
1657 ___________________________________________________________________
1658 Name: svn:keywords
1659 + Id
1661 Index: src/auto/configure
1662 ===================================================================
1663 --- src/auto/configure (.../vendor/vim/current) (revision 223)
1664 +++ src/auto/configure (.../trunk/vim) (revision 223)
1665 @@ -757,6 +757,8 @@
1666 HANGULIN_OBJ
1667 HANGULIN_SRC
1668 GUI_X_LIBS
1669 +GDB_SRC
1670 +GDB_OBJ
1671 GUITYPE
1672 GUI_LIB_LOC
1673 GUI_INC_LOC
1674 @@ -794,6 +796,7 @@
1675 enable_cscope
1676 enable_workshop
1677 enable_netbeans
1678 +enable_gdb
1679 enable_sniff
1680 enable_multibyte
1681 enable_hangulinput
1682 @@ -1465,6 +1468,7 @@
1683 --enable-rubyinterp Include Ruby interpreter.
1684 --enable-cscope Include cscope interface.
1685 --enable-workshop Include Sun Visual Workshop support.
1686 + --enable-gdb Include GDB support.
1687 --disable-netbeans Disable NetBeans integration support.
1688 --enable-sniff Include Sniff interface.
1689 --enable-multibyte Include multibyte editing support.
1690 @@ -5788,6 +5792,18 @@
1694 +echo "$as_me:$LINENO: checking --enable-gdb argument" >&5
1695 +echo $ECHO_N "checking --enable-gdb argument... $ECHO_C" >&6
1696 +# Check whether --enable-gdb or --disable-gdb was given.
1697 +if test "${enable_gdb+set}" = set; then
1698 + enableval="$enable_gdb"
1700 +else
1701 + enable_gdb="no"
1702 +fi;
1703 +echo "$as_me:$LINENO: result: $enable_gdb" >&5
1704 +echo "${ECHO_T}$enable_gdb" >&6
1706 { $as_echo "$as_me:$LINENO: checking --enable-workshop argument" >&5
1707 $as_echo_n "checking --enable-workshop argument... " >&6; }
1708 # Check whether --enable-workshop was given.
1709 @@ -10197,6 +10213,22 @@
1713 +if test "$enable_gdb" = "yes"; then
1714 + cat >>confdefs.h <<\_ACEOF
1715 +#define FEAT_GDB 1
1716 +_ACEOF
1718 + if test "x$GUITYPE" = "xNONE"; then
1719 + GDB_SRC="gdb.c clewn/gdb_lvl2.c clewn/gdb_lvl3.c clewn/misc.c clewn/obstack.c pty.c"
1720 + GDB_OBJ="objects/gdb.o objects/gdb_lvl2.o objects/gdb_lvl3.o objects/misc.o objects/obstack.o objects/pty.o"
1721 + else
1722 + GDB_SRC="gdb.c clewn/gdb_lvl2.c clewn/gdb_lvl3.c clewn/misc.c clewn/obstack.c"
1723 + GDB_OBJ="objects/gdb.o objects/gdb_lvl2.o objects/gdb_lvl3.o objects/misc.o objects/obstack.o"
1724 + fi
1729 if test "$enable_workshop" = "yes" -a -n "$SKIP_MOTIF"; then
1730 { { $as_echo "$as_me:$LINENO: error: cannot use workshop without Motif" >&5
1731 $as_echo "$as_me: error: cannot use workshop without Motif" >&2;}
1733 Property changes on: src/auto
1734 ___________________________________________________________________
1735 Name: svn:ignore
1736 + osdef.h
1737 config.status
1738 config.cache
1739 link.sed
1740 pathdef.c
1741 link.log
1742 config.log
1746 Property changes on: src/gui_at_sb.c
1747 ___________________________________________________________________
1748 Name: svn:keywords
1749 + Id
1752 Property changes on: src/gui_gtk_f.c
1753 ___________________________________________________________________
1754 Name: svn:keywords
1755 + Id
1758 Property changes on: src/ops.c
1759 ___________________________________________________________________
1760 Name: svn:keywords
1761 + Id
1764 Property changes on: src/gui_at_sb.h
1765 ___________________________________________________________________
1766 Name: svn:keywords
1767 + Id
1770 Property changes on: src/gui_gtk_f.h
1771 ___________________________________________________________________
1772 Name: svn:keywords
1773 + Id
1776 Property changes on: src/if_xcmdsrv.c
1777 ___________________________________________________________________
1778 Name: svn:keywords
1779 + Id
1782 Property changes on: src/farsi.c
1783 ___________________________________________________________________
1784 Name: svn:keywords
1785 + Id
1788 Property changes on: src/search.c
1789 ___________________________________________________________________
1790 Name: svn:keywords
1791 + Id
1794 Property changes on: src/fileio.c
1795 ___________________________________________________________________
1796 Name: svn:keywords
1797 + Id
1799 Index: src/window.c
1800 ===================================================================
1801 --- src/window.c (.../vendor/vim/current) (revision 223)
1802 +++ src/window.c (.../trunk/vim) (revision 223)
1803 @@ -6053,6 +6053,10 @@
1804 # ifdef FEAT_QUICKFIX
1805 || wp->w_p_pvw
1806 # endif
1807 +# ifdef FEAT_GDB
1808 + /* not counting a gdb window */
1809 + || gdb_isbuffer(gdb, wp->w_buffer)
1810 +# endif
1811 ) || wp == curwin)
1812 ++count;
1813 return (count <= 1);
1815 Property changes on: src/window.c
1816 ___________________________________________________________________
1817 Name: svn:keywords
1818 + Id
1821 Property changes on: src/farsi.h
1822 ___________________________________________________________________
1823 Name: svn:keywords
1824 + Id
1826 Index: src/gui_x11.c
1827 ===================================================================
1828 --- src/gui_x11.c (.../vendor/vim/current) (revision 223)
1829 +++ src/gui_x11.c (.../trunk/vim) (revision 223)
1830 @@ -148,6 +148,9 @@
1831 #ifdef FEAT_SNIFF
1832 static void gui_x11_sniff_request_cb __ARGS((XtPointer closure, int *source, XtInputId *id));
1833 #endif
1834 +#ifdef FEAT_GDB
1835 +static void gdb_request_cb __ARGS((XtPointer closure, int *source, XtInputId *id));
1836 +#endif
1837 static void gui_x11_check_copy_area __ARGS((void));
1838 #ifdef FEAT_CLIENTSERVER
1839 static void gui_x11_send_event_handler __ARGS((Widget, XtPointer, XEvent *, Boolean *));
1840 @@ -1181,7 +1184,22 @@
1842 #endif
1844 +#ifdef FEAT_GDB
1846 + * Callback function, used when data is available on the gdb file descriptor.
1847 + */
1848 +/* ARGSUSED */
1849 + static void
1850 +gdb_request_cb (closure, source, id)
1851 + XtPointer closure;
1852 + int *source;
1853 + XtInputId *id;
1855 + gdb_set_event(gdb, TRUE);
1857 +#endif
1860 * End of call-back routines
1863 @@ -2834,7 +2852,13 @@
1864 desired = (XtIMAll);
1865 while ((mask = XtAppPending(app_context)) && (mask & desired)
1866 && !vim_is_input_buf_full())
1868 +#ifdef FEAT_GDB
1869 + if (gdb_event(gdb)) /* got a gdb event */
1870 + return;
1871 +#endif
1872 XtAppProcessEvent(app_context, desired);
1877 @@ -2863,6 +2887,10 @@
1878 static int sniff_on = 0;
1879 static XtInputId sniff_input_id = 0;
1880 #endif
1881 +#ifdef FEAT_GDB
1882 + static int gdb_on = 0;
1883 + static XtInputId gdb_input_id = 0;
1884 +#endif
1886 timed_out = FALSE;
1888 @@ -2881,6 +2909,25 @@
1890 #endif
1892 +#ifdef FEAT_GDB
1893 + /* Remove call back for previous gdb connection */
1894 + if (! gdb_allowed(gdb) && gdb_on)
1896 + if (gdb_input_id)
1897 + XtRemoveInput(gdb_input_id);
1898 + gdb_on = 0;
1901 + /* A new gdb connection */
1902 + if (gdb_allowed(gdb) && !gdb_on)
1904 + /* Add gdb file descriptor to watch for available data in main loop. */
1905 + gdb_input_id = XtAppAddInput(app_context, gdb_fd(gdb),
1906 + (XtPointer)XtInputReadMask, gdb_request_cb, 0);
1907 + gdb_on = 1;
1909 +#endif
1911 if (wtime > 0)
1912 timer = XtAppAddTimeOut(app_context, (long_u)wtime, gui_x11_timer_cb,
1913 &timed_out);
1914 @@ -2920,6 +2967,15 @@
1915 XtRemoveTimeOut(timer);
1916 return OK;
1919 +#ifdef FEAT_GDB
1920 + if (wtime != 0L && gdb_allowed(gdb) && gdb_event(gdb))
1922 + if (timer != (XtIntervalId)0 && !timed_out)
1923 + XtRemoveTimeOut(timer);
1924 + return FAIL;
1926 +#endif
1928 return FAIL;
1931 Property changes on: src/gui_x11.c
1932 ___________________________________________________________________
1933 Name: svn:keywords
1934 + Id
1937 Property changes on: src/integration.c
1938 ___________________________________________________________________
1939 Name: svn:keywords
1940 + Id
1943 Property changes on: src/ex_eval.c
1944 ___________________________________________________________________
1945 Name: svn:keywords
1946 + Id
1949 Property changes on: src/integration.h
1950 ___________________________________________________________________
1951 Name: svn:keywords
1952 + Id
1954 Index: src/globals.h
1955 ===================================================================
1956 --- src/globals.h (.../vendor/vim/current) (revision 223)
1957 +++ src/globals.h (.../trunk/vim) (revision 223)
1958 @@ -1189,6 +1189,10 @@
1959 extern cursorentry_T shape_table[SHAPE_IDX_COUNT];
1960 #endif
1962 +#ifdef FEAT_GDB
1963 +EXTERN gdb_handle_T *gdb INIT(= NULL); /* gdb opaque handle */
1964 +#endif
1966 #ifdef FEAT_PRINTER
1968 * Printer stuff shared between hardcopy.c and machine-specific printing code.
1970 Property changes on: src/globals.h
1971 ___________________________________________________________________
1972 Name: svn:keywords
1973 + Id
1975 Index: src/gdb.c
1976 ===================================================================
1977 --- src/gdb.c (.../vendor/vim/current) (revision 0)
1978 +++ src/gdb.c (.../trunk/vim) (revision 223)
1979 @@ -0,0 +1,2457 @@
1980 +/* vi:set ts=8 sts=4 sw=4:
1982 + * VIM - Vi IMproved by Bram Moolenaar
1983 + * gdb support by Xavier de Gaye
1985 + * Do ":help uganda" in Vim to read copying and usage conditions.
1986 + * Do ":help credits" in Vim to see a list of people who contributed.
1988 + * $Id$
1989 + */
1991 +#include "vim.h"
1993 +#ifdef FEAT_GDB /* possibly undefined in feature.h */
1994 +# include "clewn/obstack.h"
1995 +# include "clewn/gdb.h"
1996 +# include "clewn/misc.h"
1998 +# ifndef FEAT_GUI
1999 +# include "pty.pro"
2000 +# endif
2002 +# ifdef HAVE_SYS_WAIT_H
2003 +# include <sys/wait.h>
2004 +# endif
2006 +# ifdef HAVE_FCNTL_H
2007 +# include <fcntl.h>
2008 +# endif
2010 +# if defined(HAVE_SYS_SELECT_H) && \
2011 + (!defined(HAVE_SYS_TIME_H) || defined(SYS_SELECT_WITH_SYS_TIME))
2012 +# include <sys/select.h>
2013 +# endif
2015 +# ifndef HAVE_SELECT
2016 +# ifdef HAVE_SYS_POLL_H
2017 +# include <sys/poll.h>
2018 +# else
2019 +# ifdef HAVE_POLL_H
2020 +# include <poll.h>
2021 +# endif
2022 +# endif
2023 +# endif
2025 +# ifdef HAVE_TERMIOS_H
2026 +# include <termios.h>
2027 +# else
2028 +# include <termio.h>
2029 +# endif
2031 +/* sun's sys/ioctl.h redefines symbols from termio world */
2032 +# if defined(HAVE_SYS_IOCTL_H) && !defined(sun)
2033 +# include <sys/ioctl.h>
2034 +# endif
2036 +# define SCROLLOFF 6 /* min lines around frame highlite */
2037 +# define MAXMEM 64L /* 'maxmem' option */
2039 +/* Not allowed after ^O in INS REP mode or from the input-line window */
2040 +# define NOT_ALLOWED_MODE (restart_edit != 0 || cmdwin_type != 0)
2042 +/* storage for mtrace hooks */
2043 +# if defined(GDB_MTRACE) && defined(HAVE_MTRACE)
2044 +__ptr_t (*s_malloc) (size_t, const void *);
2045 +void (*s_free) (void *, const void *);
2046 +__ptr_t (*s_realloc) (void *, size_t, const void *);
2047 +# endif /* GDB_MTRACE */
2049 +static int module_state = -1; /* initial state (not OK, nor FAIL) */
2050 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2051 +static char_u *inputrc; /* readline inputrc file name */
2052 +# endif
2054 +/* The gdb keyword */
2055 +typedef struct
2057 + int type;
2058 + char_u *keyword; /* keyword */
2059 + char_u *tail; /* optional tail */
2060 + regprog_T *regprog; /* compiled regexp */
2061 +} token_T;
2063 +static token_T tokens[] = {
2064 + {CMD_DIR, (char_u *)"dir", (char_u *)"ectory", NULL},
2065 + {CMD_DETACH, (char_u *)"det", (char_u *)"ach", NULL},
2066 + {CMD_SHELL, (char_u *)"she", (char_u *)"ll", NULL},
2067 + {CMD_STEPI, (char_u *)"si", (char_u *)"", NULL},
2068 + {CMD_STEPI, (char_u *)"stepi", (char_u *)"", NULL},
2069 + {CMD_STEPI, (char_u *)"ni", (char_u *)"", NULL},
2070 + {CMD_STEPI, (char_u *)"nexti", (char_u *)"", NULL},
2071 + {CMD_EXECF, (char_u *)"fil", (char_u *)"e", NULL},
2072 + {CMD_EXECF, (char_u *)"ex", (char_u *)"ec-file", NULL},
2073 + {CMD_EXECF, (char_u *)"cor", (char_u *)"e-file", NULL},
2074 + {CMD_BREAK, (char_u *)"b", (char_u *)"reak", NULL},
2075 + {CMD_BREAK, (char_u *)"tb", (char_u *)"reak", NULL},
2076 + {CMD_BREAK, (char_u *)"hb", (char_u *)"reak", NULL},
2077 + {CMD_BREAK, (char_u *)"thb", (char_u *)"reak", NULL},
2078 + {CMD_DISPLAY, (char_u *)"disp", (char_u *)"lay", NULL},
2079 + {CMD_CREATEVAR, (char_u *)"cr", (char_u *)"eatevar", NULL},
2080 + {CMD_UP_SILENT, (char_u *)"up-", (char_u *)"silently", NULL},
2081 + {CMD_UP, (char_u *)"up", (char_u *)"", NULL},
2082 + {CMD_DOWN_SILENT,(char_u *)"down-", (char_u *)"silently", NULL},
2083 + {CMD_DOWN, (char_u *)"do", (char_u *)"wn", NULL},
2084 + {CMD_FRAME, (char_u *)"f", (char_u *)"rame", NULL},
2085 + {CMD_DISABLE, (char_u *)"disab", (char_u *)"le", NULL},
2086 + {CMD_DELETE, (char_u *)"del", (char_u *)"ete", NULL},
2087 + {CMD_SLECT_FRAME,(char_u *)"sel", (char_u *)"ect-frame", NULL},
2088 + {CMD_SYMF, (char_u *)"sy", (char_u *)"mbol-file", NULL},
2089 + {CMD_SYMF, (char_u *)"add-sy", (char_u *)"mbol-file", NULL},
2090 + {CMD_ANY, NULL, NULL, NULL}
2093 +/* The gdb pattern */
2094 +typedef struct {
2095 + int id; /* pattern id */
2096 + char_u *str; /* string pattern */
2097 + regprog_T *regprog; /* compiled regexp */
2098 +} pattern_T;
2100 +static pattern_T patterns[] = {
2101 + {PAT_DIR, (char_u *)"^\\s*Source directories searched:\\s*\\(.*\\)$", NULL},
2102 + {PAT_CHG_ANNO, (char_u *)"^\\s*set\\s\\+an\\%[notate]\\s\\+.*$", NULL},
2103 + {PAT_ADD, (char_u *)"^0x0*\\(\\x\\+\\)\\>", NULL},
2104 + {PAT_PID, (char_u *)"^\\s*at\\%[tach] \\+\\([0-9]\\+\\) *$", NULL},
2105 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2106 + {PAT_SOURCE, (char_u *)"^\\s*\\([^:]*\\):\\([^:]*\\):[^:]*:[^:]*:0x0*\\(\\x\\+\\)$", NULL},
2107 + {PAT_QUERY, (char_u *)"^.*(y or n) \\=$", NULL},
2108 + {PAT_YES, (char_u *)"^\\s*\\(\\<y\\%[es]\\>\\)\\s*$", NULL},
2109 + {PAT_SFILE, (char_u *)"^Symbols from\\s*\"\\([^\"]\\+\\)", NULL},
2110 + {PAT_BP_CONT, (char_u *)"^\\s*\\(c\\)\\>\\|^\\s*\\(cont\\)\\%[inue]\\>", NULL},
2111 + {PAT_ASM_FUNC, (char_u *)"^\\(\\S\\{-1,}\\)\\%((.*)\\)* .*in section .text$", NULL},
2112 + {PAT_ASM_FUNC_P, (char_u *)"^.*<\\(\\S\\{-1,}\\)\\%(+\\d\\+\\)*>$", NULL},
2113 + {PAT_FRAME, (char_u *)"^#\\d\\+\\s\\+0x0*\\(\\x\\+\\)\\>", NULL},
2114 +# endif
2115 +# ifdef GDB_LVL2_SUPPORT
2116 + /* MUST add '.*' at end of each info (possibly last) breakpoint field
2117 + * pattern because GDB adds the hit count, in a new line, after
2118 + * printing the last field and within its annotation context */
2119 + {PAT_BP_ASM, (char_u *)"^<\\(\\S\\+\\)+\\d\\+>.*$\\|^<\\(\\S\\+\\)>.*$", NULL},
2120 + {PAT_BP_SOURCE, (char_u *)"^.\\{-}\\(\\S\\+\\):\\(\\d\\+\\).*$", NULL},
2121 + {PAT_DISPLAY, (char_u *)"^\\s*disp\\%[lay]\\s*$", NULL},
2122 + {PAT_DISPINFO, (char_u *)"^\\(\\d\\+\\):", NULL},
2123 + {PAT_CREATEVAR, (char_u *)"^\\s*cr\\%[eatevar]\\>\\s*\\(.*\\)$", NULL},
2124 +# endif
2125 +# ifdef GDB_LVL3_SUPPORT
2126 + {PAT_CRVAR_FMT, (char_u *)"^\\s*cr\\%[eatevar]\\>\\s*\\(/[tdxo]\\)\\{,1}\\>\\s*\\(.*\\)$", NULL},
2127 + {PAT_INFO_FRAME, (char_u *)"^Stack level \\(\\d\\+\\), frame at ", NULL},
2128 +# endif
2129 + {0, NULL, NULL}
2132 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2133 +/* gdb readline inputrc file content */
2134 +static char *readline[] = {
2135 + "set show-all-if-ambiguous on\n",
2136 + "set completion-query-items 20\n", /* max without prompting user */
2137 + "Control-u: unix-line-discard\n",
2138 + NULL
2140 +# endif
2142 +/* Gdb process mgmt */
2143 +# define GDB_STATE(i,s) (((i) != NULL) ? ((((gdb_T *)(i))->state) & (s)):FALSE)
2144 +static void gdb_abort __ARGS((void));
2145 +static int start_gdb_process __ARGS((gdb_T *, char_u *));
2146 +static int module_init __ARGS((void));
2147 +static void module_end __ARGS((void));
2148 +static void clear_gdb_T __ARGS((gdb_T *));
2149 +static int exec_gdb __ARGS((gdb_T *));
2151 +/* Window and buffer mgmt */
2152 +static win_T *ftowin __ARGS((char_u *));
2153 +static buf_T *buffer_create __ARGS((char_u *, int, int, int, char_u *));
2154 +static void cursor_atbot __ARGS((gdb_T *));
2155 +static int line_append __ARGS((gdb_T *, char_u *));
2157 +/* Utilities */
2158 +static void histdel __ARGS((char_u *));
2160 +/** Create gdb, return its handle */
2161 + gdb_handle_T *
2162 +gdb_new()
2164 + gdb_T *gdb;
2166 +# if defined(GDB_MTRACE) && defined(HAVE_MTRACE)
2167 + mtrace();
2168 + mv_hooks;
2169 +#endif
2170 + /* register an abort function for when allocating memory fails */
2171 + xatabort(gdb_abort);
2172 + obstack_alloc_failed_handler = gdb_abort;
2174 + gdb = (gdb_T *)xcalloc((unsigned)sizeof(gdb_T));
2175 + gdb->state = GS_INIT;
2176 + gdb->pid = (pid_t)-1;
2178 + return (gdb_handle_T *)gdb;
2181 +/** Abort GDB */
2182 + static void
2183 +gdb_abort()
2185 +#if defined(GDB_MTRACE) && defined(HAVE_MTRACE)
2186 + muntrace();
2187 +#endif
2188 + fprintf(stderr, "\nvirtual memory exhausted\n");
2189 + mch_exit(1);
2192 +/** Delete gdb */
2193 + void
2194 +gdb_delete(pgdb)
2195 + gdb_handle_T **pgdb;
2197 + gdb_T *this;
2199 + if (pgdb == NULL || (this = (gdb_T *)*pgdb) == NULL)
2200 + return;
2202 + if (this->buf != NULL) /* wipe out the buffer */
2203 + (void)do_bufdel(DOBUF_WIPE, (char_u *)"", 1, 0, this->buf->b_fnum, TRUE);
2205 + gdb_close(this);
2206 + module_end(); /* release module resources */
2207 + clear_gdb_T(this);
2208 + xfree(this);
2209 + *pgdb = NULL;
2210 +# if defined(GDB_MTRACE) && defined(HAVE_MTRACE)
2211 + muntrace();
2212 +# endif
2215 +/** Return TRUE when gdb is running */
2216 + int
2217 +gdb_isrunning(gdb)
2218 + gdb_handle_T *gdb;
2220 + return GDB_STATE(gdb, GS_UP);
2223 +/** Return gdb pty file descriptor */
2224 + int
2225 +gdb_fd(gdb)
2226 + gdb_handle_T *gdb;
2228 + return (gdb != NULL ? ((gdb_T *)gdb)->fd : -1);
2231 +/** Return gdb process id */
2232 + pid_t
2233 +gdb_pid(gdb)
2234 + gdb_handle_T *gdb;
2236 + return (gdb != NULL ? ((gdb_T *)gdb)->pid : (pid_t)-1);
2239 +/** Return TRUE when buf is the gdb buffer */
2240 + int
2241 +gdb_isbuffer(gdb, buf)
2242 + gdb_handle_T *gdb;
2243 + buf_T *buf; /* buffer to check for */
2245 + return ((gdb != NULL && ((gdb_T *)gdb)->buf != NULL)
2246 + ? ((gdb_T *)gdb)->buf == buf : FALSE);
2249 +/** Return TRUE when gdb output may be processed from low level functions */
2250 + int
2251 +gdb_allowed(gdb)
2252 + gdb_handle_T *gdb;
2254 + return (GDB_STATE(gdb, GS_UP) && GDB_STATE(gdb, GS_ALLOWED));
2257 +/** Return TRUE when a gdb event is pending */
2258 + int
2259 +gdb_event(gdb)
2260 + gdb_handle_T *gdb;
2262 + return GDB_STATE(gdb, GS_EVENT);
2265 +/** Return TRUE when there is a pending SIGCHLD */
2266 + int
2267 +gdb_sigchld(gdb)
2268 + gdb_handle_T *gdb;
2270 + return GDB_STATE(gdb, GS_SIGCHLD);
2273 +/** Set or unset a gdb event */
2274 + void
2275 +gdb_set_event (gdb, set)
2276 + gdb_handle_T *gdb;
2277 + int set; /* TRUE when setting event */
2279 + if (gdb == NULL)
2280 + return;
2282 + ((gdb_T *)gdb)->state &= ~GS_EVENT;
2283 + if (set)
2284 + ((gdb_T *)gdb)->state |= GS_EVENT;
2287 +/** Set or unset a SIGCHLD event */
2288 + void
2289 +gdb_set_sigchld (gdb, set)
2290 + gdb_handle_T *gdb;
2291 + int set; /* TRUE when setting SIGCHLD event */
2293 + if (gdb == NULL)
2294 + return;
2296 + ((gdb_T *)gdb)->state &= ~GS_SIGCHLD;
2297 + if (set)
2298 + ((gdb_T *)gdb)->state |= GS_SIGCHLD;
2301 +/**
2302 + * Entry point for safe_vgetc().
2303 + * Set a flag to prevent recursion and enable gdb to read its pseudo tty
2304 + * in the low level routines.
2305 + * Return safe_vgetc return value.
2306 + */
2307 + int
2308 +gdb_safe_vgetc(gdb)
2309 + gdb_handle_T *gdb;
2311 + gdb_T *this = (gdb_T *)gdb;
2312 + int s_a;
2313 + int rc;
2315 + if (this == NULL)
2316 + return safe_vgetc();
2318 + s_a = (this->state & GS_ALLOWED);
2320 + /* set state GS_ALLOWED TRUE when called from top level,
2321 + * not in visual mode and not in the input-line window */
2322 + if (this->recurse == 0 && cmdwin_type == 0 && !VIsual_active)
2324 + this->state |= GS_ALLOWED;
2325 + s_a = FALSE;
2327 + else
2328 + this->state &= ~GS_ALLOWED;
2330 + this->recurse++;
2331 + rc = safe_vgetc(); /* call it now */
2332 + this->recurse--;
2334 + this->state &= ~GS_ALLOWED;
2335 + if (s_a)
2336 + this->state |= GS_ALLOWED;
2337 + return rc;
2340 +/** Take note Vim is freeing a buffer */
2341 + void
2342 +gdb_buffer_free(gdb, buf)
2343 + gdb_handle_T *gdb;
2344 + buf_T *buf; /* buffer being freed */
2346 + gdb_T *this = (gdb_T *)gdb;
2347 + bpinfo_T *p, **pt;
2348 + int i;
2350 + if (this != NULL)
2352 + if (this->buf == buf)
2353 + this->buf = NULL;
2355 + /* variables window buffer */
2356 + else if (this->var_buf == buf)
2358 + this->var_buf = NULL;
2360 + /* call mode specifice var_delete */
2361 + if (this->var_delete != NULL)
2362 + this->var_delete(this); /* delete all variables */
2365 + /* asm buffers */
2366 + else
2367 + for (i = 0; i < this->pool.max; i++)
2368 + if (this->pool.buf[i] == buf)
2370 + this->pool.buf[i] = NULL;
2371 + break;
2374 + /* remove in bpinfo list the records corresponding to the
2375 + * signs in buf
2376 + * the signs themselves are supposed to be removed by Vim
2377 + * in free_buffer()*/
2378 + for (pt = &(this->bpinfo); *pt != NULL; )
2380 + p = *pt;
2381 + if (p->buf == buf)
2383 + gdb_undefine_sign(p->typenr);
2384 + *pt = p->next; /* unlink record */
2385 + xfree(p);
2387 + else
2388 + pt = &(p->next);
2393 +# define STL_GDB "gdb "
2394 +# define STL_SEP1 "- "
2395 +# define STL_SEP2 " ["
2396 +# define STL_TAIL "]"
2397 +/** Write gdb status line label in dst */
2398 + void
2399 +gdb_label(gdb, buf, dst, len)
2400 + gdb_handle_T *gdb;
2401 + buf_T *buf; /* stl's buffer */
2402 + char_u *dst; /* where to write the label */
2403 + size_t len; /* label max length */
2405 + gdb_T *this = (gdb_T *)gdb;
2406 + size_t cnt = 0;
2407 + char_u *fname;
2408 + size_t l;
2409 +# define STLCPY(s) {\
2410 + l = (((s)!=NULL) ? STRLEN((s)):0);\
2411 + l = MIN(l,len-cnt-1); \
2412 + STRNCPY(dst+cnt,(s),l); \
2413 + cnt+=l; \
2416 + /* a console window displaying gdb buffer */
2417 + if (this != NULL && this->buf == buf && (this->state & GS_UP)
2418 + && dst != NULL && len > 0)
2420 + STLCPY(STL_GDB);
2421 + if (this->sfile != NULL)
2423 + STLCPY(STL_SEP1);
2424 + fname = gettail(this->sfile);
2425 + STLCPY(fname);
2428 + STLCPY(STL_SEP2);
2429 + STLCPY(this->status);
2430 + STLCPY(STL_TAIL);
2431 + *(dst + cnt) = NUL;
2435 +/** Send a cmd to gdb */
2436 + void
2437 +gdb_docmd(gdb, cmd)
2438 + gdb_handle_T *gdb;
2439 + char_u *cmd; /* gdb cmd */
2441 + gdb_T *this = (gdb_T *)gdb;
2443 + if (this == NULL || NOT_ALLOWED_MODE)
2444 + return;
2446 + /* start gdb */
2447 + this->state &= ~GS_STARTED;
2448 + if (!(this->state & GS_UP) && start_gdb_process(this, cmd) == FAIL)
2449 + return;
2451 + /* process first cmd later */
2452 + if (this->state & GS_STARTED)
2453 + return;
2455 + /* pop up gdb console */
2456 + gdb_popup_console(this);
2458 + /* The next statement has the following purpose:
2459 + * When stepping by hitting continuously key 'I', the discarded command
2460 + * give_warning (see few lines below) may be permanently displayed losing
2461 + * thus all meaning: better to clear the cmd line before possibly
2462 + * outputing the msg. */
2463 + msg_clr_cmdline();
2465 + /* accept one cmd at a time, allow intr */
2466 + if (cmd != NULL && *cmd != NUL && *(cmd + STRLEN(cmd) - 1) == KEY_INTERUPT)
2467 + this->oob.state |= OS_INTR;
2468 + else if (this->oob.state & OS_CMD)
2470 + give_warning((char_u *)"GDB busy: command discarded, please retry", TRUE);
2471 + return;
2473 + else
2474 + this->oob.idx = -1; /* needed when last oob was aborted with OS_QUITs */
2475 + this->oob.state |= OS_CMD;
2477 + /* call mode specific docmd */
2478 + if (this->gdb_docmd != NULL)
2479 + this->gdb_docmd(this, cmd);
2482 +/** Set the cmd to be inserted later in the input-line window */
2483 + void
2484 +gdb_setwinput(gdb, cmd)
2485 + gdb_handle_T *gdb;
2486 + char_u *cmd; /* cmd to insert */
2488 + gdb_T *this = (gdb_T *)gdb;
2490 + if (this == NULL || NOT_ALLOWED_MODE)
2491 + return;
2493 + if (cmd == NULL)
2494 + cmd = (char_u *)"";
2496 + if (STRCHR(cmd, (int)NL) != NULL) /* assert no NL in cmd */
2497 + return;
2499 + xfree(this->winput_cmd);
2500 + this->winput_cmd = vim_strsave_escaped(cmd, (char_u *)"\"");
2503 +/** Return TRUE if we are opening the gdb input-line window */
2504 + int
2505 +gdb_iswinput(gdb)
2506 + gdb_handle_T *gdb;
2508 + return (gdb != NULL ? ((gdb_T *)gdb)->winput_cmd != NULL : FALSE);
2511 +/** Launch the input-line window */
2512 + void
2513 +gdb_winput(gdb)
2514 + gdb_handle_T *gdb;
2516 + gdb_T *this = (gdb_T *)gdb;
2517 + int s_silent = cmd_silent;
2518 + char_u *cedit = NULL;
2519 + char_u *cmd = NULL;
2520 + char_u *res = NULL;
2521 + char_u key[2] = {NUL, NUL};
2522 + char_u *trim;
2523 + char_u *p;
2524 + char_u *q = NULL; /* initialized to please the compiler */
2525 + char_u *r;
2527 + if (this == NULL || NOT_ALLOWED_MODE)
2528 + return;
2530 + if (this->winput_cmd == NULL || !stuff_empty() || typebuf.tb_len != 0)
2531 + goto fin;
2533 + /* pop up gdb console */
2534 + if (this->state & GS_UP)
2535 + gdb_popup_console(this);
2537 + /* insert in typebuf: <C-F> . "a" . winput_cmd */
2538 + /* 'a' start insert mode */
2539 + p = NULL;
2540 + key[0] = Ctrl_F;
2541 + gdb_cat(&p, key);
2542 + gdb_cat(&p, (char_u *)"a");
2543 + gdb_cat(&p, this->winput_cmd);
2545 + if (ins_typebuf(p, REMAP_NONE, 0, TRUE, TRUE) == FAIL)
2547 + xfree(p);
2548 + goto fin;
2550 + xfree(p);
2552 + /* set cedit */
2553 + (void)get_option_value((char_u *)"cedit", NULL, &cedit, OPT_GLOBAL);
2554 + set_option_value((char_u *)"cedit", 0L, key, OPT_GLOBAL);
2556 + /* Launch the input-line window */
2557 + /* careful: must free cmd with vim_free */
2558 + cmd_silent = FALSE;
2559 + cmd = getcmdline_prompt((int)'@', NULL, 0, EXPAND_NOTHING, NULL);
2560 + cmd_silent = s_silent;
2561 + msg_didout = FALSE;
2563 + /* restore cedit */
2564 + if (cedit != NULL)
2566 + set_option_value((char_u *)"cedit", 0L, cedit, OPT_GLOBAL);
2567 + xfree(cedit);
2569 + cursor_atbot(this);
2571 + /* Do not start gdb when interrupt */
2572 + if (!(this->state & GS_UP)
2573 + && (cmd == NULL || STRCHR(cmd, KEY_INTERUPT) != NULL))
2575 + histdel(cmd);
2576 + goto fin;
2579 + /* User typed ^C^C: send an interrupt */
2580 + if (cmd == NULL)
2582 + key[0] = KEY_INTERUPT;
2583 + gdb_docmd(gdb, key);
2585 + else /* Cleanup history */
2587 + /* p first word, q first white after last word */
2588 + trim = (char_u *)clewn_strsave((char *)cmd);
2589 + r = p = skipwhite(trim);
2590 + do {
2591 + q = skiptowhite(r);
2592 + r = skipwhite(q);
2593 + } while (*r != NUL);
2595 + if ((res = STRCHR(cmd, '\t')) != NULL)
2597 + histdel(cmd);
2598 + *(res + 1) = NUL; /* trim after <Tab> */
2600 + else if ((res = STRCHR(cmd, KEY_INTERUPT)) != NULL)
2602 + histdel(cmd);
2603 + *(res + 1) = NUL; /* trim after ^Z */
2605 + /* trim surrounding spaces for syntax highliting */
2606 + else if (trim != NULL && (p != trim || *q != NUL))
2608 + histdel(cmd);
2609 + if (*q != NUL)
2610 + *q = NUL;
2611 + if (*p != NUL)
2612 + add_to_history(HIST_INPUT, p, FALSE, NUL);
2614 + xfree(trim);
2616 + FREE(this->winput_cmd);
2618 + /* send cmd */
2619 + gdb_docmd(gdb, cmd);
2621 + vim_free(cmd);
2622 + return;
2624 +fin:
2625 + vim_free(cmd);
2626 + FREE(this->winput_cmd);
2629 +/**
2630 + * Invoke parse_output and compute time left to wait for a character in
2631 + * the caller, mch_inchar.
2632 + * Return time left or -1 when mch_inchar must trigger the input-line window.
2633 + */
2634 + long
2635 +gdb_process_output(gdb, wtime, start)
2636 + gdb_handle_T *gdb;
2637 + long wtime; /* time left */
2638 + void *start; /* start time in mch_inchar */
2640 + gdb_T *this = (gdb_T *)gdb;
2641 +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
2642 + struct timeval * pstart = (struct timeval *)start;
2643 + struct timeval tv;
2644 +# endif
2645 + int rc;
2647 + if (this != NULL && (this->state & GS_ALLOWED))
2649 + if (this->parse_output == NULL)
2650 + return (wtime > 0 ? wtime : 0L);
2652 + /* call mode specific parser */
2653 + this->state &= ~GS_ALLOWED; /* prevent recursion */
2654 + rc = this->parse_output(this);
2655 + this->state |= GS_ALLOWED;
2657 + this->state &= ~GS_EVENT;
2659 + if (rc)
2660 + return -1L;
2662 + if (wtime > 0)
2664 +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
2665 + /* compute new remaining time */
2666 + if (pstart != NULL)
2668 + gettimeofday(&tv, NULL);
2669 + wtime -= (tv.tv_sec - pstart->tv_sec) * 1000L
2670 + + (tv.tv_usec - pstart->tv_usec) / 1000L;
2671 + pstart->tv_sec = tv.tv_sec; /* reset start time */
2672 + pstart->tv_usec = tv.tv_usec;
2674 + else
2675 +# endif
2677 + /* estimated gdb processing is 10 msecs */
2678 + wtime -= 10L;
2682 + return (wtime > 0 ? wtime : 0L);
2685 +/* Start a gdb process; return OK when succcess, FAIL otherwise */
2686 + static int
2687 +start_gdb_process(this, cmd)
2688 + gdb_T *this;
2689 + char_u *cmd; /* the first gdb cmd */
2691 + char_u *res = NULL;
2692 + char_u *p;
2693 + int i;
2695 + clear_gdb_T(this);
2697 + if (module_init() == OK && exec_gdb(this) == OK)
2699 + /* save first non empty cmd */
2700 + if (cmd != NULL)
2702 + p = skipwhite(cmd);
2703 + if (*p != NUL)
2704 + this->firstcmd = (char_u *)clewn_strsave((char *)cmd);
2707 + /* create variables window buffer */
2708 + if (p_gvar != NULL && *p_gvar != NUL)
2709 + this->var_buf = buffer_create(p_gvar, TRUE, TRUE, TRUE, (char_u *)"gdbvar");
2711 + /* create pool of asm buffers */
2712 + this->pool.max = MIN(ABS(p_asm), ASM_MAX_BUFF);
2713 + this->pool.idx = 0;
2714 + for (i = 0; i < this->pool.max; i++)
2716 + gdb_cat(&res, (char_u *)ASM_BUF_NAME);
2717 + gdb_cat(&res, gdb_itoa(i + 1));
2719 + this->pool.buf[i] = buffer_create(res, FALSE, FALSE, FALSE, NULL);
2720 + this->pool.age[i] = ASM_OLD;
2721 + FREE(res);
2723 + this->pool.last = i + 1;
2724 + cursor_atbot(this);
2726 + this->directories = (char_u *)clewn_strsave(",,"); /* path: current directory */
2727 + return OK;
2729 + return FAIL;
2733 + * Initialize this module: set inputrc file, define signs, compile regexp.
2734 + * Return OK when succcess, FAIL otherwise.
2735 + */
2736 + static int
2737 +module_init()
2739 + char_u *s_cpo = p_cpo;
2740 + pattern_T *pat;
2741 + token_T *tok;
2742 + exarg_T eap;
2743 + char_u *pattern;
2744 + int len;
2745 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2746 + char **p;
2747 + int fd;
2748 +# endif
2750 + if (module_state == -1)
2752 + module_state = FAIL; /* do it only once */
2754 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2755 + /* Set gdb readline inputrc file contents
2756 + * careful: must free inputrc with vim_free
2757 + * We don't know yet if we are going to use GDB/MI, so we need to
2758 + * setup inputrc just in case, even though it might never be used */
2759 + if ((inputrc = vim_tempname((int)'A')) != NULL
2760 + && (fd = mch_open((char *)inputrc, O_CREAT | O_RDWR | O_EXTRA, 0644)) >= 0)
2762 + for (p = readline; *p; p++)
2763 + write(fd, *p, strlen(*p));
2764 + close(fd);
2765 + vim_setenv((char_u *)"INPUTRC", inputrc);
2767 +# endif
2769 + /* define breakpoint and frame signs */
2770 + do_highlight((char_u *)"gdb_bp term=bold ctermbg=Blue ctermfg=Black guibg=Blue guifg=Black", 0, 0);
2771 + do_highlight((char_u *)"gdb_dbp term=bold ctermbg=Green ctermfg=Black guibg=Green guifg=Black", 0, 0);
2772 + do_highlight((char_u *)"gdb_fr term=bold ctermbg=DarkYellow ctermfg=Black guibg=DarkYellow guifg=Black", 0, 0);
2774 + /* We use for frame and phantom sign type numbers the same
2775 + * value as their sign numbers. They are respectively FRAME_SIGN
2776 + * and PHANTOM_SIGN */
2777 + eap.arg = (char_u *)clewn_strsave(
2778 + "define 1 linehl=gdb_fr text==> texthl=Search");
2779 + ex_sign(&eap);
2780 + xfree(eap.arg);
2782 + eap.arg = (char_u *)clewn_strsave(
2783 + "define 2 linehl=Normal text=.. texthl=NonText");
2784 + ex_sign(&eap);
2785 + xfree(eap.arg);
2787 + /* make sure no sign in use */
2788 + buf_delete_all_signs();
2790 + /* Compile patterns */
2791 + p_cpo = (char_u *)""; /* so that 'l' flag doesn't work */
2792 + for (pat = patterns; pat->str != NULL; pat++)
2793 + if ((pat->regprog = vim_regcomp(pat->str, TRUE)) == NULL)
2794 + goto fin;
2796 + /* Compile tokens */
2797 + for (tok = tokens; tok->keyword != NULL; tok++)
2799 + len = (tok->tail != NULL ? STRLEN(tok->tail) : 0);
2801 + /* pattern: '^\s*\(\<token\%[option]\>\).*$' */
2802 + pattern = NULL;
2803 + gdb_cat(&pattern, (char_u *)"^\\s*\\(\\<");
2804 + gdb_cat(&pattern, tok->keyword);
2806 + if (len != 0)
2808 + gdb_cat(&pattern, (char_u *)"\\%[");
2809 + gdb_cat(&pattern, tok->tail);
2810 + gdb_cat(&pattern, (char_u *)"]");
2813 + gdb_cat(&pattern, (char_u *)"\\>\\).*$");
2815 + if ((tok->regprog = vim_regcomp(pattern, TRUE)) == NULL)
2817 + xfree(pattern);
2818 + goto fin;
2820 + xfree(pattern);
2823 + module_state = OK;
2825 +fin:
2826 + p_cpo = s_cpo;
2827 + return module_state;
2830 +/* Release module resources */
2831 + static void
2832 +module_end()
2834 + pattern_T *pat;
2835 + token_T *tok;
2836 + exarg_T eap;
2838 + module_state = -1;
2840 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2841 + if (inputrc != NULL)
2843 + mch_remove(inputrc);
2844 + vim_free(inputrc);
2845 + inputrc = NULL;
2847 +# endif
2849 + /* remove signs */
2850 + do_highlight((char_u *)"clear gdb_bp", 0, 0);
2851 + do_highlight((char_u *)"clear gdb_dbp", 0, 0);
2852 + do_highlight((char_u *)"clear gdb_fr", 0, 0);
2854 + /* make sure no sign in use */
2855 + buf_delete_all_signs();
2857 + emsg_skip++;
2858 + eap.arg = (char_u *)clewn_strsave("undefine 1");
2859 + ex_sign(&eap);
2860 + xfree(eap.arg);
2862 + eap.arg = (char_u *)clewn_strsave("undefine 2");
2863 + ex_sign(&eap);
2864 + xfree(eap.arg);
2865 + emsg_skip--;
2867 + /* patterns an tokens */
2868 + for (pat = patterns; pat->str != NULL; pat++)
2869 + if (pat->regprog != NULL)
2870 + FREE(pat->regprog);
2872 + for (tok = tokens; tok->keyword != NULL; tok++)
2873 + if (tok->regprog != NULL)
2874 + FREE(tok->regprog);
2877 +/* Initialize a gdb_T structure */
2878 + static void
2879 +clear_gdb_T(this)
2880 + gdb_T *this;
2882 + if (this != NULL)
2884 + this->pid = (pid_t)-1;
2885 +#if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2886 + this->height = 0;
2887 +#endif
2888 + this->state = GS_INIT;
2889 + FREE(this->status);
2890 + this->recurse = 0;
2892 + this->cmd_type = CMD_ANY;
2893 +#if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2894 + this->cli_cmd.state = CS_START;
2895 + this->cli_cmd.cnt = 0;
2896 + FREE(this->cli_cmd.gdb);
2897 + FREE(this->cli_cmd.readline);
2898 + FREE(this->cli_cmd.echoed);
2899 +#endif
2901 + FREE(this->firstcmd);
2902 + FREE(this->winput_cmd);
2903 + FREE(this->directories);
2904 + FREE(this->sfile);
2906 +#if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2907 + this->note = ANO_NONE;
2908 + this->annoted = FALSE;
2909 + this->newline = FALSE;
2910 + FREE(this->annotation);
2911 +#endif
2912 + FREE(this->line);
2913 + FREE(this->pc);
2914 + FREE(this->frame_pc);
2915 + FREE(this->oob_result);
2916 + FREE(this->asm_add);
2917 + FREE(this->asm_func);
2919 +#if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
2920 + this->bp_state = 0;
2921 + gdb_free_bplist(&(this->tmplist));
2922 +#endif
2923 + FREE(this->record);
2924 + this->cont = FALSE;
2925 + gdb_free_bplist(&(this->bpinfo));
2926 + this->frame_curlvl = -1;
2927 + this->frame_lnum = (linenr_T) -1;
2928 + FREE(this->frame_fname);
2931 + this->fr_buf = NULL;
2933 + this->oob.state = 0;
2934 + this->oob.idx = -1;
2936 + this->pool.hilite = FALSE;
2938 + /* free mode specific data within gdb_T */
2939 + if (this->clear_gdb_T != NULL)
2940 + this->clear_gdb_T(this);
2942 + this->oobfunc = NULL;
2943 + this->parse_output = NULL;
2944 + this->gdb_docmd = NULL;
2945 + this->var_delete = NULL;
2946 + this->clear_gdb_T = NULL;
2950 +/* Spawn a gdb process; return OK when sucess, FAIL otherwise */
2951 + static int
2952 +exec_gdb(this)
2953 + gdb_T *this;
2955 + char_u *err = NULL;
2956 + int fd = -1; /* slave pty file descriptor */
2957 + char *tty; /* pty name */
2958 + buf_T *buf;
2959 +# ifdef HAVE_TERMIOS_H
2960 + struct termios tio;
2961 +# else
2962 + struct termio tio;
2963 +# endif
2965 + /* process already running */
2966 + if (this->pid != (pid_t)-1 && waitpid(this->pid, NULL, WNOHANG) == 0)
2967 + return OK;
2969 + /* Open pty */
2970 + if ((this->fd = OpenPTY(&tty)) < 0
2971 + || (fd = open(tty, O_RDWR|O_NOCTTY|O_EXTRA, 0)) < 0
2972 + || SetupSlavePTY(fd) == -1)
2974 + err = (char_u *)"Cannot open gdb pty";
2975 + goto err;
2978 + /* Set terminal attributes */
2979 +# ifdef HAVE_TERMIOS_H
2980 + if (tcgetattr(fd, &tio) == 0)
2981 +# else
2982 + if (ioctl(fd, TCGETA, &tio) >= 0)
2983 +# endif
2985 + tio.c_oflag &= ~ONLCR; /* don't map NL to CR-NL on output */
2986 + tio.c_cc[VINTR] = KEY_INTERUPT;
2987 +# ifdef HAVE_TERMIOS_H
2988 + if (tcsetattr(fd, TCSAFLUSH, &tio) != 0)
2989 +# else
2990 + if (ioctl(fd, TCSETA, &tio) < 0)
2991 +# endif
2993 + err = (char_u *)"Cannot set gdb pty";
2994 + goto err;
2997 + else
2999 + err = (char_u *)"Cannot get gdb pty";
3000 + goto err;
3003 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
3004 +# if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
3006 + struct winsize win;
3008 + /* set tty height */
3009 + if (ioctl(fd, TIOCGWINSZ, &win) >= 0)
3011 + win.ws_row = LPP_LINES;
3012 + if (ioctl(fd, TIOCSWINSZ, &win) >= 0)
3013 + this->height = LPP_LINES;
3016 +# endif
3017 +# endif
3019 + /* Fork */
3020 + if ((this->pid = fork()) == (pid_t)-1)
3022 + err = (char_u *)"Cannot fork gdb";
3023 + goto err;
3025 +/* The child */
3026 + else if (this->pid == (pid_t)0)
3028 + /* Grab control of terminal (from `The GNU C Library' (glibc-2.3.1)) */
3029 + setsid();
3030 +# ifdef TIOCSCTTY
3031 + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1)
3032 + _exit(1);
3033 +# else
3034 + { int newfd;
3035 + char *fdname = ttyname(fd);
3037 + /* This might work (it does on Linux) */
3038 + if (fdname)
3040 + if (fd != 0)
3041 + close (0);
3042 + if (fd != 1)
3043 + close (1);
3044 + if (fd != 2)
3045 + close (2);
3046 + newfd = open(fdname, O_RDWR);
3047 + close(newfd);
3050 +# endif
3052 + close(0); dup(fd);
3053 + close(1); dup(fd);
3054 + close(2); dup(fd);
3056 + if (fd > 2)
3057 + close(fd);
3059 + close(this->fd);
3061 + /* close all swap files: on Cygwin, Windows fail to unlink the swap
3062 + * files while there is still an open file descriptor held by
3063 + * another (child) process */
3064 + for (buf = firstbuf; buf != NULL; buf = buf->b_next)
3065 + if (buf->b_ml.ml_mfp != NULL
3066 + && buf->b_ml.ml_mfp->mf_fd >= 0)
3067 + close(buf->b_ml.ml_mfp->mf_fd);
3069 +# ifdef GDB_MI_SUPPORT
3070 + if (p_gdbmi)
3072 + /* MI mi2 is available starting with GDB 6.0 */
3073 + execlp(p_gdp, p_gdp, "--interpreter=mi2", NULL);
3074 + _exit(EXIT_FAILURE);
3076 +# endif
3077 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
3078 + clewn_exec((char *)p_gdp);
3079 +# endif /* defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT) */
3081 + _exit(EXIT_FAILURE);
3083 +/* The parent */
3084 + else
3086 + close(fd);
3087 + this->state |= GS_UP;
3088 + this->state |= GS_STARTED;
3090 +# ifdef GDB_MI_SUPPORT
3091 + if (p_gdbmi)
3093 + if (gdb_setup_mi(this) != OK)
3095 + gdb_cat(&err, (char_u *)"Cannot start GDB program \"");
3096 + gdb_cat(&err, p_gdp);
3097 + gdb_cat(&err, (char_u *)"\" (MI)");
3098 + if (err != NULL)
3100 + EMSG(_(err));
3101 + xfree(err);
3103 + this->state = GS_INIT;
3104 + return FAIL;
3106 + else
3107 + return OK;
3109 +# endif
3110 +# if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
3111 + if (gdb_setup_cli(this) != OK)
3113 + this->state = GS_INIT;
3114 + return FAIL;
3116 + else
3117 + return OK;
3118 +# endif
3120 + this->state = GS_INIT;
3121 + return FAIL;
3123 +err:
3124 + if (this->fd >= 0)
3125 + close(this->fd);
3126 + if (fd >= 0)
3127 + close(fd);
3128 + if (err != NULL)
3129 + EMSG(_(err));
3130 + return FAIL;
3133 +# define CG_QUIT "quit\n"
3134 +# define CG_YES "yes\n"
3135 +# define CG_TERM "Terminated\n\n"
3136 +# define CG_SEP "####################################\n"
3137 +# define CG_POLL 100
3138 +/* Close gdb process */
3139 + void
3140 +gdb_close(this)
3141 + gdb_T *this;
3143 + pid_t pid;
3144 + int i;
3145 + int rc;
3147 + if (this->state & GS_CLOSING) /* prevent recursive calls */
3148 + return;
3149 + this->state |= GS_CLOSING;
3151 + this->syntax = TRUE; /* force syntax highlite */
3152 + gdb_write_buf(this, (char_u *)CG_TERM, TRUE);
3153 + gdb_write_buf(this, (char_u *)CG_SEP, TRUE);
3154 + this->syntax = FALSE;
3156 + if (this->buf != NULL)
3157 + close_windows(this->buf, FALSE);
3159 + buf_delete_all_signs();
3161 + /* wipe out variables window buffer */
3162 + if (this->var_buf != NULL)
3163 + (void)do_bufdel(DOBUF_WIPE, (char_u *)"", 1, 0, this->var_buf->b_fnum, TRUE);
3165 + /* wipe out asm buffers */
3166 + for (i = 0; i < this->pool.max; i++)
3167 + if (this->pool.buf[i] != NULL)
3168 + (void)do_bufdel(DOBUF_WIPE, (char_u *)"", 1, 0, this->pool.buf[i]->b_fnum, TRUE);
3170 + /* free breakpoints table */
3171 + gdb_free_bplist(&(this->bpinfo));
3173 + /* a) attempt to gracefully terminate gdb process
3174 + * b) if this fails, SIGTERM it
3175 + * c) if this fails, too bad, just return */
3176 + if (this->pid != (pid_t)-1)
3178 + pid = waitpid(this->pid, NULL, WNOHANG);
3180 + if ((pid == (pid_t)-1 && errno == ECHILD) || pid == this->pid)
3181 + close(this->fd);
3182 + else /* still running */
3184 + char c = KEY_INTERUPT;
3185 + int killed = FALSE;
3186 + char_u buf[MAX_BUFFSIZE];
3187 + int t;
3189 + /* a) write an interrupt followed by a 'quit' cmd */
3190 + write(this->fd, &c, 1);
3191 + if (gdb_read(this, buf, MAX_BUFFSIZE, 1000) >= 0)
3193 + write(this->fd, CG_QUIT, strlen(CG_QUIT));
3194 + while ((rc = gdb_read(this, buf, MAX_BUFFSIZE, 100)) > 0)
3197 + if (rc != -1)
3198 + write(this->fd, CG_YES, strlen(CG_YES));
3200 + close(this->fd);
3202 + /* make sure gdb is terminated: poll for waitpid() */
3203 + for (t = 0; !killed; t += CG_POLL)
3205 + /* 1 second elapsed since start of polling for waitpid */
3206 + if (t >= 1000 )
3208 +# ifdef SIGTERM
3209 + /* b) kill it now */
3210 + kill(this->pid, SIGTERM);
3211 +# endif
3212 + killed = TRUE;
3215 + mch_delay(CG_POLL, TRUE);
3216 + pid = waitpid(this->pid, NULL, WNOHANG);
3217 + if ((pid == (pid_t)-1 && errno == ECHILD) || pid == this->pid)
3218 + break;
3221 + MSG_ATTR(_("GDB terminated"), hl_attr(HLF_E));
3224 + gdb_redraw(curbuf); /* force redrawing */
3225 + this->state = GS_INIT;
3226 + this->pid = (pid_t)-1;
3229 +/* Highlite asm_add line; return TRUE when asm_add found in asm buffer */
3230 + int
3231 +gdb_as_frset(this, obs)
3232 + gdb_T *this;
3233 + struct obstack *obs;
3235 + char_u *ptrn = NULL;
3236 + int first = this->pool.idx;
3237 + pos_T pos;
3238 + win_T *win;
3239 + int i;
3241 + if (this->asm_func == NULL)
3242 + return FALSE;
3244 + /* age asm buffers */
3245 + for (i = 0; i < this->pool.max; i++)
3246 + if (this->pool.age[i] < ASM_OLD)
3247 + this->pool.age[i]++;
3249 + if (this->asm_add != NULL)
3251 + obstack_strcat(obs, "^\\s*0x0*");
3252 + obstack_strcat0(obs, this->asm_add);
3253 + ptrn = (char_u *)obstack_finish(obs);
3256 + if (ptrn != NULL)
3258 + /* Search all asm buffers whose name start with this->asm_func
3259 + * for ptrn.
3260 + * Start with the current one. */
3261 + i = first;
3262 + do
3264 + pos.lnum = 1;
3265 + pos.col = 0;
3267 + if (this->pool.buf[i] != NULL
3268 + && STRSTR(this->pool.buf[i]->b_fname, this->asm_func) != NULL
3269 + && !(this->pool.buf[i]->b_ml.ml_flags & ML_EMPTY)
3270 + && searchit(NULL, this->pool.buf[i], &pos,
3271 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
3273 + this->pool.idx = i;
3274 + this->pool.age[i] = 0;
3275 + this->pool.lnum = pos.lnum;
3277 + if (this->pool.hilite)
3278 + gdb_fr_set(this, NULL, NULL, obs);
3279 + else if ((win = gdb_btowin(this->pool.buf[i])) != NULL)
3280 + gdb_set_cursor(win, pos.lnum);
3282 + FREE(this->asm_add);
3283 + return TRUE;
3285 + } while ((i = ++i % this->pool.max) != first);
3288 + return FALSE;
3292 + * Highlight line within frame
3293 + * Return -1 when failing to load the buffer, 0 otherwise
3294 + */
3295 + int
3296 +gdb_fr_set(this, file, line, obs)
3297 + gdb_T *this;
3298 + char_u *file;
3299 + linenr_T *line;
3300 + struct obstack *obs;
3302 + win_T *oldwin = curwin;
3303 + buf_T *buf = NULL;
3304 + linenr_T lnum;
3306 + /* Do not set frame hilite when this breakpoint has a 'commands'
3307 + * with a 'continue' statement */
3308 + if (this->cont)
3310 + this->cont = FALSE;
3311 + return 0;
3314 + if (line == NULL) /* in asm window */
3316 + buf = this->pool.buf[this->pool.idx];
3317 + lnum = this->pool.lnum;
3319 + else /* in source file */
3320 + lnum = *line;
3322 + if (buf != NULL || file != NULL)
3324 + if (gdb_edit_file(this, buf, file, lnum, obs) != NULL)
3326 + /* MUST redraw the screen before calling update_debug_sign():
3327 + * update_debug_sign() invokes win_update()
3328 + * the screen might have been scrolled when Vim ask the
3329 + * user to confirm changes made to the previous buffer */
3330 + gdb_redraw(curwin->w_buffer);
3332 + gdb_fr_lite(this, curwin->w_buffer, lnum, obs);
3334 + else {
3335 + win_goto(oldwin);
3336 + return -1;
3339 + return 0;
3342 +/* Highlite frame */
3343 + void
3344 +gdb_fr_lite(this, buf, lnum, obs)
3345 + gdb_T *this;
3346 + buf_T *buf; /* where to highlite */
3347 + linenr_T lnum; /* line number */
3348 + struct obstack *obs;
3350 + buf_T *disped = NULL;
3352 + if (obs) {} /* keep compiler happy */
3354 + if (buf == NULL || lnum <= 0)
3355 + return;
3357 + /*
3358 + * Remove previous frame sign:
3359 + * GDB sends ANO_FRAME_INVALID annotations whenever stepping, running, etc...
3360 + * and these annotations invoke gdb_fr_unlite() that turn off the previous frame sign.
3361 + * But when moving along the stack frame with GDB 'up', 'down', 'frame' commands,
3362 + * we don't get annotations and must turn off the previous frame sign.
3363 + */
3364 + if (this->fr_buf != NULL)
3365 + disped = gdb_unlite(FRAME_SIGN);
3367 + /* add new frame highlite */
3368 + buf_addsign(buf, FRAME_SIGN, lnum, FRAME_SIGN);
3369 + update_debug_sign(buf, lnum);
3371 + /* remove phantom highlite */
3372 + disped = gdb_unlite(PHANTOM_SIGN);
3374 + this->fr_buf = buf;
3375 + if (gdb_btowin(buf) != NULL)
3376 + disped = buf;
3378 + gdb_redraw(disped); /* only when displayed */
3381 +/* Unlite frame */
3382 + void
3383 +gdb_fr_unlite(this)
3384 + gdb_T *this;
3386 + buf_T *disped = NULL;
3387 + buf_T *buf = this->fr_buf;
3388 + linenr_T lnum;
3390 + if (buf == NULL)
3391 + return;
3392 + this->fr_buf = NULL;
3394 + /* To avoid screen blinks: replace with phantom sign */
3395 + if (gdb_btowin(buf) != NULL && (lnum = BUFLASTL(buf)) > 0)
3397 + buf_addsign(buf, PHANTOM_SIGN, lnum, PHANTOM_SIGN);
3398 + update_debug_sign(buf, lnum);
3401 + disped = gdb_unlite(FRAME_SIGN);
3402 + gdb_redraw(disped); /* only when displayed */
3406 + * Unlite a sign.
3407 + * Return last displayed buffer that contained this sign.
3408 + */
3409 + buf_T *
3410 +gdb_unlite(id)
3411 + int id; /* sign id */
3413 + buf_T *disped = NULL;
3414 + buf_T *buf;
3415 + linenr_T lnum;
3417 + for (buf = firstbuf; buf != NULL; buf = buf->b_next)
3418 + if ((lnum = buf_delsign(buf, id)) != 0)
3420 + update_debug_sign(buf, lnum);
3421 + if (gdb_btowin(buf) != NULL)
3422 + disped = buf;
3424 + return disped;
3428 + * Define a breakpoint sign. There is one sign type per breakpoint
3429 + * sign in order to have breakpoints numbers as the sign text.
3430 + * Returns sign type number or -1 if error.
3431 + */
3432 + int
3433 +gdb_define_sign(id, enabled)
3434 + int id; /* breakpoint number */
3435 + int enabled; /* TRUE when breakpoint is enabled */
3437 + exarg_T eap;
3438 + char_u text[NUMBUFLEN];
3439 + int r;
3441 + if (id <= 0)
3442 + return -1;
3444 + /* the sign text is two chars max */
3445 + if (id < 100)
3446 + STRCPY(text, gdb_itoa(id));
3447 + else
3449 + if ((r = id % 100) < 10)
3451 + text[0] = '0';
3452 + STRCPY(text + 1, gdb_itoa(r));
3454 + else
3455 + STRCPY(text, gdb_itoa(r));
3458 + /* With id = 1 and enabled TRUE, build the following:
3459 + * "define 3 linehl=gdb_bp text=1 texthl=LineNr" */
3460 + eap.arg = NULL;
3461 + gdb_cat(&(eap.arg), (char_u *)"define ");
3462 + gdb_cat(&(eap.arg), gdb_itoa(BP_SIGN_ID(id)));
3463 + gdb_cat(&(eap.arg), (char_u *)" linehl=");
3465 + if (enabled)
3466 + gdb_cat(&(eap.arg), (char_u *)"gdb_bp");
3467 + else
3468 + gdb_cat(&(eap.arg), (char_u *)"gdb_dbp");
3470 + gdb_cat(&(eap.arg), (char_u *)" text=");
3471 + gdb_cat(&(eap.arg), text);
3472 + gdb_cat(&(eap.arg), (char_u *)" texthl=LineNr");
3474 + ex_sign(&eap);
3475 + xfree(eap.arg);
3476 + return BP_SIGN_ID(id);
3479 +/* Undefine a breakpoint sign */
3480 + void
3481 +gdb_undefine_sign(typenr)
3482 + int typenr; /* sign type number to undefine */
3484 + exarg_T eap;
3486 + if (typenr <= 0)
3487 + return;
3489 + emsg_skip++;
3490 + eap.arg = NULL;
3491 + gdb_cat(&(eap.arg), (char_u *)"undefine ");
3492 + gdb_cat(&(eap.arg), gdb_itoa(typenr));
3493 + ex_sign(&eap);
3494 + xfree(eap.arg);
3495 + emsg_skip--;
3498 +/** Return the (first) console window where is displayed gdb */
3499 + win_T *
3500 +gdb_window(gdb)
3501 + gdb_handle_T *gdb;
3503 + return (gdb != NULL ? gdb_btowin(((gdb_T *)gdb)->buf): NULL);
3506 +/* Return (first) window where buf is displayed */
3507 + win_T *
3508 +gdb_btowin(buf)
3509 + buf_T *buf;
3511 + win_T *win;
3513 + if (buf != NULL)
3514 + for (win = firstwin; win != NULL; win = win->w_next)
3515 + if (win->w_buffer == buf)
3516 + return win;
3517 + return NULL;
3520 +/* Return (first) window where file fname is displayed */
3521 + static win_T *
3522 +ftowin(fname)
3523 + char_u *fname;
3525 + buf_T *buf = NULL;
3526 + char_u *name;
3528 + /* first make the name into a full path name
3529 + * force expansion, get rid of symbolic links */
3530 + if (fname != NULL && (name = FullName_save(fname, TRUE)) != NULL)
3532 + buf = buflist_findname(name);
3533 + xfree(name);
3535 + return gdb_btowin(buf);
3538 +/* Pop up gdb console, load the buffer when first time */
3539 + void
3540 +gdb_popup_console(this)
3541 + gdb_T *this;
3543 + win_T *oldwin = curwin;
3544 + char_u *name = NULL;
3545 + long s_mm = p_mm;
3546 + long splitbelow;
3547 + long splitright;
3548 + int flags;
3550 + /* already displayed */
3551 + if (this->buf != NULL && gdb_btowin(this->buf) != NULL)
3552 + return;
3554 + /* get a unique name */
3555 + if (this->buf == NULL &&
3556 + (! (this->state & GS_UP)
3557 + || (name = vim_tempname((int)'A')) == NULL))
3558 + return;
3560 + /* get splitbelow and splitright options values */
3561 + (void) get_option_value((char_u *)"sb", &splitbelow, NULL, OPT_LOCAL);
3562 + (void) get_option_value((char_u *)"spr", &splitright, NULL, OPT_LOCAL);
3564 + if (splitbelow) {
3565 + if (splitright)
3566 + flags = WSP_BOT; /* bottom */
3567 + else
3568 + flags = WSP_VERT | WSP_TOP; /* left */
3570 + else {
3571 + if (splitright)
3572 + flags = WSP_VERT | WSP_BOT; /* right */
3573 + else
3574 + flags = WSP_TOP; /* the default: top */
3577 + /* create new window */
3578 + if (win_split(p_pvh > 0 ? p_pvh : 0, flags) == FAIL)
3580 + vim_free(name); /* free name with vim_free */
3581 + return;
3584 + if (this->buf == NULL)
3586 + p_mm = MAXMEM; /* buffer max virtual memory */
3587 + (void)do_ecmd(0, name, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
3588 + p_mm = s_mm;
3590 + vim_free(name); /* free name with vim_free */
3591 + msg_clr_cmdline();
3592 + curwin->w_alt_fnum = 0; /* no alternate */
3593 + this->buf = curbuf;
3595 + /* set buffer local options
3596 + * wrap, linebreak, nomodifiable, nolist
3597 + * filetype=gdbvim - bufhidden=hide - buftype=nowrite */
3598 + set_option_value((char_u *)"wrap", 0L, NULL, OPT_LOCAL);
3599 + set_option_value((char_u *)"lbr", 1L, NULL, OPT_LOCAL);
3600 + set_option_value((char_u *)"ma", 0L, NULL, OPT_LOCAL);
3601 + set_option_value((char_u *)"list", 0L, NULL, OPT_LOCAL);
3602 + set_option_value((char_u *)"syn", 0L, (char_u *)"gdbvim", OPT_LOCAL);
3603 + set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL);
3604 + set_option_value((char_u *)"bt", 0L, (char_u *)"nowrite", OPT_LOCAL);
3605 + set_option_value((char_u *)"bl", 0L, NULL, OPT_LOCAL);
3607 + else if (this->buf != curbuf)
3609 + set_curbuf(this->buf, DOBUF_GOTO);
3611 + /* nobuflisted must be set each time it's displayed */
3612 + set_option_value((char_u *)"bl", 0L, NULL, OPT_LOCAL);
3615 + /* return to previous window */
3616 + if (win_valid(oldwin))
3618 + prevwin = oldwin;
3619 + win_goto(oldwin);
3623 +/* Create an assembly buffer */
3624 + static buf_T *
3625 +buffer_create(name, wrap, modifiable, listed, syntax)
3626 + char_u *name; /* buffer name */
3627 + int wrap; /* TRUE when option 'wrap' is set */
3628 + int modifiable; /* TRUE when option 'modifiable' is set */
3629 + int listed; /* TRUE when option 'listed' is set */
3630 + char_u *syntax; /* buffer syntax */
3632 + win_T *oldwin = curwin;
3633 + buf_T *buf = NULL;
3634 + win_T *wp;
3635 + garray_T sizes;
3637 + /* save window sizes */
3638 + win_size_save(&sizes);
3640 +# ifdef FEAT_AUTOCMD
3641 + ++autocmd_busy;
3642 +# endif
3643 + /* create a tmp window */
3644 + if (win_split(0, WSP_BOT) == OK)
3646 + /* create the asm buffer empty */
3647 + (void)do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
3648 + gdb_as_setname(name);
3649 +# ifdef FEAT_AUTOCMD
3650 + /* allow autocommands for loading syntax */
3651 + --autocmd_busy;
3652 +# endif
3653 + set_option_value((char_u *)"wrap", (long)wrap, NULL, OPT_LOCAL);
3654 + set_option_value((char_u *)"ma", (long)modifiable, NULL, OPT_LOCAL);
3655 + set_option_value((char_u *)"bl", (long)listed, NULL, OPT_LOCAL);
3657 + if (syntax != NULL)
3658 + set_option_value((char_u *)"syn", 0L, syntax, OPT_LOCAL);
3660 + set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
3661 + set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
3662 + set_option_value((char_u *)"list", 0L, NULL, OPT_LOCAL);
3663 + set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL);
3664 +# ifdef FEAT_AUTOCMD
3665 + ++autocmd_busy;
3666 +# endif
3667 + if (curwin != oldwin)
3669 + buf = curbuf;
3670 + wp = curwin;
3671 + win_goto(oldwin);
3672 + win_close(wp, FALSE);
3675 +# ifdef FEAT_AUTOCMD
3676 + --autocmd_busy;
3677 +# endif
3678 + win_size_restore(&sizes);
3679 + ga_clear(&sizes);
3680 + return buf;
3683 +/* Set a unique buffer name */
3684 + void
3685 +gdb_as_setname(name)
3686 + char_u *name; /* buffer name */
3688 + char_u *res = NULL;
3689 + int s_t = p_title;
3690 + int s_i = p_icon;
3691 + int i = 0;
3692 + char_u *buf;
3694 + p_title = p_icon = FALSE;
3695 + do
3697 + buf = gdb_itoa(i);
3698 + if (i == 0)
3699 + *buf = NUL;
3700 + i++;
3702 + FREE(res);
3703 + gdb_cat(&res, name);
3704 + gdb_cat(&res, buf);
3705 + } while (setfname(curbuf, res, NULL, FALSE) == FAIL);
3707 + xfree(res);
3708 + p_title = s_t;
3709 + p_icon = s_i;
3713 + * Clear an asm buffer of its content and signs.
3714 + * Rename it to an asm generic name.
3715 + */
3716 + void
3717 +gdb_clear_asmbuf(this, buf)
3718 + gdb_T *this;
3719 + buf_T *buf; /* asm buffer to clear */
3721 + buf_T *oldbuf = curbuf;
3722 + char_u *res = NULL;
3723 + bpinfo_T *p, **pt;
3724 + linenr_T lnum;
3726 + if (buf == NULL)
3727 + return;
3729 + curbuf = buf;
3731 + /* rename buffer if its name is not a generic name */
3732 + if ((buf->b_sfname == NULL || STRSTR(buf->b_sfname, ASM_BUF_NAME) != buf->b_sfname))
3734 + gdb_cat(&res, (char_u *)ASM_BUF_NAME);
3735 + gdb_cat(&res, gdb_itoa(this->pool.last++));
3736 + gdb_as_setname(res);
3737 + FREE(res);
3740 + lnum = BUFLASTL(buf);
3741 + while (lnum-- > 0) /* clear buffer */
3742 + ml_delete(buf->b_ml.ml_line_count, FALSE);
3743 + curbuf = oldbuf;
3745 + /* remove all the buffer signs:
3746 + * in buf
3747 + * their corresponding bpinfo record
3748 + * their corresponding sign type */
3749 + for (pt = &(this->bpinfo); *pt != NULL; )
3751 + p = *pt;
3752 + if (p->buf == buf)
3754 + buf_delsign(buf, BP_SIGN_ID(p->id));
3755 + gdb_undefine_sign(p->typenr);
3756 + *pt = p->next; /* unlink record */
3757 + xfree(p);
3759 + else
3760 + pt = &(p->next);
3763 + /* remove frame sign if present */
3764 + if (this->fr_buf == buf)
3766 + gdb_unlite(FRAME_SIGN);
3767 + this->fr_buf = NULL;
3771 +/* Put back gdb console's last line at bottom. */
3772 +/* needed after win_close messes up gdb topline when 'equalalways' on */
3773 + static void
3774 +cursor_atbot(this)
3775 + gdb_T *this;
3777 + win_T *oldwin = curwin;
3778 + win_T *win;
3780 + if ((win = gdb_btowin(this->buf)) != NULL)
3782 + curwin = win;
3783 + curbuf = curwin->w_buffer;
3784 + scroll_cursor_bot(0, TRUE);
3785 + redraw_later(VALID);
3786 + curwin = oldwin;
3787 + curbuf = curwin->w_buffer;
3791 +/* Append line to gdb buffer */
3792 + static int
3793 +line_append(this, line)
3794 + gdb_T *this;
3795 + char_u *line; /* line to append */
3797 + linenr_T lnum = BUFLASTL(this->buf);
3798 + char_u *res = NULL;
3799 + win_T *win;
3800 + int rc;
3802 +# define LN_PREFIX " "
3803 + /* disable syntax highliting by prefixing with LN_PREFIX */
3804 + if (! this->syntax)
3806 + gdb_cat(&res, (char_u *)LN_PREFIX);
3807 + gdb_cat(&res, line);
3808 + if ((line = res) == NULL)
3809 + return FAIL;
3812 + /* first line ever: remove empty line after the one just inserted */
3813 + if ((rc = ml_append(lnum, line, 0, 0)) == OK && lnum == 0)
3814 + ml_delete(this->buf->b_ml.ml_line_count, FALSE);
3816 + if ((win = gdb_btowin(this->buf)) != NULL)
3817 + redraw_win_later(win, NOT_VALID);
3819 + xfree(res);
3820 + return rc;
3823 +/* Append to/Replace last line in gdb buffer */
3824 + void
3825 +gdb_write_buf(this, chunk, add)
3826 + gdb_T *this;
3827 + char_u *chunk; /* a chunk may contain one, many or no NL */
3828 + int add; /* TRUE when chunk is added */
3830 + win_T *oldwin = curwin;
3831 + win_T *win;
3832 + char_u *start;
3833 + char_u *ptr;
3834 + int cnt; /* number of lines appended */
3836 + if (chunk == NULL || this->buf == NULL)
3837 + return;
3839 + /* make a copy */
3840 + chunk = (char_u *)clewn_strsave((char *)chunk);
3842 + /* set curbuf to buf */
3843 + curbuf = this->buf;
3845 + /* delete last line */
3846 + if (!add)
3847 + ml_delete(this->buf->b_ml.ml_line_count, FALSE);
3849 + /* append to buffer line after line */
3850 + cnt = 0;
3851 + for (ptr = start = chunk; *ptr != NUL; ptr++)
3853 + if (*ptr == NL)
3855 + *ptr = NUL;
3856 + line_append(this, start);
3857 + start = ptr + 1;
3858 + cnt++;
3862 + /* handle an empty line or last non NL terminated stuff */
3863 + if (start == chunk || *start != NUL)
3865 + line_append(this, start);
3866 + cnt++;
3869 + changed_lines(this->buf->b_ml.ml_line_count - cnt, 0,
3870 + this->buf->b_ml.ml_line_count, cnt);
3872 + /* window displayed */
3873 + if ((win = gdb_btowin(this->buf)) != NULL)
3875 + /* update top line */
3876 + curwin = win;
3877 + curwin->w_cursor.lnum = this->buf->b_ml.ml_line_count;
3878 + update_topline();
3880 + /* status line changed */
3881 + curwin->w_redr_status = TRUE;
3884 + curwin = oldwin;
3885 + curbuf = curwin->w_buffer;
3886 + xfree(chunk);
3890 + * Edit a file in a non-console window.
3891 + * Use buf if non NULL, otherwise fname using gdb source path to find the file.
3892 + * Return NULL if error, curwin otherwise.
3893 + */
3894 + win_T *
3895 +gdb_edit_file(this, buf, fname, lnum, obs)
3896 + gdb_T *this;
3897 + buf_T *buf; /* asm buffer to load */
3898 + char_u *fname; /* file name */
3899 + linenr_T lnum; /* line number */
3900 + struct obstack *obs;
3902 +#ifdef GDB_LVL3_SUPPORT
3903 + char_u * source_cur = this->lvl3.source_cur; /* GDB current source */
3904 + char_u * source_list = this->lvl3.source_list; /* GDB source list */
3905 +#else
3906 + char_u * source_cur = NULL;
3907 + char_u * source_list = NULL;
3908 +#endif
3909 + char_u *fpn;
3910 + win_T *win;
3911 + int i;
3913 + if (obs) {} /* keep comiler happy */
3915 + if (buf == NULL && (fname == NULL || *fname == NUL))
3916 + return NULL;
3918 +#ifdef FEAT_GUI
3919 + need_mouse_correct = TRUE;
3920 +#endif
3922 + /* found a window where source is already displayed */
3923 + if ((win = gdb_btowin(buf)) != NULL || (win = ftowin(fname)) != NULL)
3925 + gdb_set_cursor(win, lnum);
3926 + win_goto(win);
3927 + return win;
3929 + win = NULL;
3931 + /* use a non-console window */
3932 + if (curbuf == this->buf)
3933 + for (win = firstwin; win != NULL; win = win->w_next)
3934 + if (win->w_buffer != this->buf)
3936 + win_goto(win);
3937 + break;
3940 + if (win == NULL)
3941 + win = curwin;
3943 + if (buf == NULL)
3945 + /* get the first existing full path name in GDB source directories
3946 + * matching this name */
3947 + if ((fpn = (char_u *)get_fullpath((char *)fname, (char *)this->directories,
3948 + (char *)source_cur, (char *)source_list, obs)) == NULL)
3950 + return NULL;
3953 + (void)do_ecmd(0, fpn, NULL, NULL, lnum,
3954 + (P_HID(curbuf) ? ECMD_HIDE : 0) + ECMD_OLDBUF, curwin);
3956 + else if (buf != curbuf)
3957 + set_curbuf(buf, DOBUF_GOTO);
3959 + /* asm buffers are not listed */
3960 + if (buf != NULL && buf == curbuf)
3961 + for (i = 0; i < this->pool.max; i++)
3962 + if (this->pool.buf[i] == buf)
3964 + set_option_value((char_u *)"bl", 0L, NULL, OPT_LOCAL);
3965 + break;
3968 + if (win_valid(win))
3970 + gdb_set_cursor(win, lnum);
3971 + prevwin = win;
3972 + return win;
3975 + return NULL;
3978 +/* Set cursor to lnum with at least SCROLLOFF lines around it */
3979 + void
3980 +gdb_set_cursor(win, lnum)
3981 + win_T *win;
3982 + linenr_T lnum;
3984 + win_T *oldwin = curwin;
3985 + long s_so = p_so;
3987 + if (win != NULL)
3989 + curwin = win;
3990 + curbuf = curwin->w_buffer;
3992 + curwin->w_cursor.lnum = lnum;
3993 + curwin->w_cursor.col = 0;
3994 + check_cursor();
3996 + if (p_so < SCROLLOFF )
3997 + p_so = SCROLLOFF;
3998 + update_topline();
4000 + win->w_redr_status = TRUE;
4002 + p_so = s_so;
4003 + curwin = oldwin;
4004 + curbuf = curwin->w_buffer;
4008 +/* Display a cmd line busy msg */
4009 + void
4010 +gdb_msg_busy(str)
4011 + char_u *str;
4013 + static char *prop[] = { "/", "-", "\\", "|" };
4014 + static char busy[IOSIZE];
4015 + static int cnt;
4017 + /* set busy string */
4018 + if (str != NULL)
4020 + STRNCPY(busy, str, IOSIZE - 1);
4021 + busy[IOSIZE - 1] = NUL;
4023 + else
4025 + msg_scroll = FALSE;
4026 + msg_start();
4027 + msg_outtrans((char_u *)busy);
4028 + msg_puts((char_u *)" [");
4029 + msg_puts((char_u *)prop[(++cnt % 4)]);
4030 + msg_puts((char_u *)"]");
4031 + msg_clr_eos();
4032 + out_flush();
4036 +/* Set status and and mark stl dirty */
4037 + void
4038 +gdb_status(this, status, obs)
4039 + gdb_T *this;
4040 + char_u *status; /* gdb status */
4041 + struct obstack *obs;
4043 + win_T *win;
4045 + if (obs) {} /* keep comiler happy */
4047 + xfree(this->status);
4048 + this->status = (char_u *)clewn_strsave((char *)status);
4049 + if ((win = gdb_btowin(this->buf)) != NULL)
4050 + win->w_redr_status = TRUE;
4053 +/* Update screen when buf is displayed */
4054 +/* needed only from low level functions, not elsewhere */
4055 + void
4056 +gdb_redraw(buf)
4057 + buf_T *buf;
4059 + int s_r = RedrawingDisabled;
4060 + int s_lz = p_lz;
4061 + win_T *win;
4063 + if (buf == NULL)
4064 + return;
4066 + for (win = firstwin; win != NULL; win = win->w_next)
4067 + if (win->w_buffer == buf)
4069 + RedrawingDisabled = 0;
4070 + p_lz = FALSE;
4071 + update_screen(0);
4072 + RedrawingDisabled = s_r;
4073 + p_lz = s_lz;
4075 + /* reset cursor */
4076 + cursor_on();
4077 + setcursor();
4078 + out_flush();
4079 + break;
4083 +/* Do the OOB_COMPLETE part of an oob cmd and send the next one */
4084 + void
4085 +gdb_oob_send(this, obs)
4086 + gdb_T *this;
4087 + struct obstack *obs;
4089 + int keep = FALSE; /* when TRUE, do not switch to next oob function */
4090 + char *res = NULL;
4091 + int *pi = &(this->oob.idx);
4092 + int s_a = (this->state & GS_ALLOWED);
4094 + /* prevent recursive calls to parse_output() since breakpoint
4095 + * or frame highlighting may cause Vim to query the user when
4096 + * changes have been made in the previous buffer */
4097 + this->state &= ~GS_ALLOWED;
4099 + if (this->oobfunc == NULL)
4100 + return;
4102 + if (*pi == -1)
4104 + this->oob.state &= ~OS_INTR;
4105 + if (this->oob.state & OS_QUIT)
4106 + goto quit;
4109 + if (*pi >= 0 && (this->oobfunc)[*pi].oob != NULL) /* assert != NULL */
4111 + if ((this->oobfunc)[*pi].oob(this, OOB_COMPLETE, NULL, obs) != NULL)
4112 + keep = TRUE;
4114 + if (this->oob.state & OS_QUIT)
4115 + goto quit;
4118 + if (! keep)
4119 + ++(*pi);
4121 + while ((this->oobfunc)[*pi].oob != NULL && !(this->oob.state & OS_INTR))
4123 + if ((res = (this->oobfunc)[*pi].oob(this, OOB_CMD, NULL, obs)) != NULL)
4125 + this->oob.cnt = 0;
4127 + /* send the command to GDB */
4128 + write(this->fd, res, strlen(res));
4130 + this->state &= ~GS_ALLOWED;
4131 + if (s_a)
4132 + this->state |= GS_ALLOWED;
4133 + return;
4136 + ++(*pi);
4139 + *pi = -1;
4140 +quit:
4141 + this->oob.state &= ~OS_CMD;
4142 + this->oob.state &= ~OS_QUIT;
4144 + this->state &= ~GS_ALLOWED;
4145 + if (s_a)
4146 + this->state |= GS_ALLOWED;
4149 +/* Receive out of band response to idx cmd */
4150 + void
4151 +gdb_oob_receive(this, chunk, obs)
4152 + gdb_T *this;
4153 + char_u *chunk; /* response (possibly incomplete) */
4154 + struct obstack *obs;
4156 + char_u *res = NULL;
4157 + int s_a = (this->state & GS_ALLOWED);
4159 + /* prevent recursive calls to parse_output() since breakpoint
4160 + * or frame highlighting may cause Vim to query the user when
4161 + * changes have been made in the previous buffer */
4162 + this->state &= ~GS_ALLOWED;
4164 + if (this->oobfunc == NULL)
4165 + return;
4167 + if(IS_OOBACTIVE(this))
4169 + /* silently discard when interrupted */
4170 + if (!(this->oob.state & OS_INTR) && chunk != NULL)
4172 + if (this->parser != PS_PREPROMPT && this->parser != PS_PROMPT
4173 + && (this->oobfunc)[this->oob.idx].oob != NULL) /* assert != NULL */
4175 + this->oob.cnt++;
4176 + (void)(this->oobfunc)[this->oob.idx].oob(this, OOB_COLLECT, chunk, obs);
4178 + this->state &= ~GS_ALLOWED;
4179 + if (s_a)
4180 + this->state |= GS_ALLOWED;
4181 + return;
4185 + /* keep the last prompt */
4186 + if (this->parser == PS_PREPROMPT)
4188 + gdb_cat(&res, this->line);
4189 + gdb_cat(&res, chunk);
4190 + xfree(this->line);
4191 + this->line = res;
4195 + this->state &= ~GS_ALLOWED;
4196 + if (s_a)
4197 + this->state |= GS_ALLOWED;
4201 + * Fill up buff with a NUL terminated string of max size - 1 bytes from gdb.
4202 + * Return bytes read count, -1 if error or zero for nothing to read.
4203 + */
4204 + int
4205 +gdb_read(this, buff, size, wtime)
4206 + gdb_T *this;
4207 + char_u *buff; /* where to write */
4208 + int size; /* buff size */
4209 + int wtime; /* msecs time out, -1 wait forever */
4211 + int len;
4212 + int rc;
4213 +# ifndef HAVE_SELECT
4214 + struct pollfd fds;
4216 + fds.fd = this->fd;
4217 + fds.events = POLLIN;
4218 +# else
4219 + struct timeval tv;
4220 + struct timeval start_tv;
4221 + fd_set rfds;
4223 + FD_ZERO(&rfds);
4224 + FD_SET(this->fd, &rfds);
4226 +# ifdef HAVE_GETTIMEOFDAY
4227 + if (wtime >= 0)
4228 + gettimeofday(&start_tv, NULL);
4229 +# endif
4230 +# endif
4232 + if (size <= 0 || buff == NULL || !(this->state & GS_UP))
4233 + return -1;
4235 + /* make sure there is some data to read */
4236 + while (1)
4238 + if (this->state & GS_SIGCHLD)
4239 + goto close;
4241 +# ifndef HAVE_SELECT
4242 + if ((rc = poll(&fds, 1, wtime)) > 0)
4243 +# else
4244 + if (wtime >= 0)
4246 + tv.tv_sec = wtime / 1000;
4247 + tv.tv_usec = (wtime % 1000) * (1000000/1000);
4250 + if ((rc = select(this->fd + 1, &rfds, NULL, NULL, (wtime >= 0) ? &tv : NULL)) > 0)
4251 +# endif
4252 + break;
4254 + if (rc == -1 && errno == EINTR)
4256 + if (wtime >= 0)
4258 + /* compute remaining wait time */
4259 +# if ! defined(HAVE_SELECT) || ! defined(HAVE_GETTIMEOFDAY)
4260 + /* guess: interrupted halfway, gdb processing 10 msecs */
4261 + wtime = wtime / 2 - 10L;
4262 +# else
4263 + gettimeofday(&tv, NULL);
4264 + wtime -= (tv.tv_sec - start_tv.tv_sec) * 1000L
4265 + + (tv.tv_usec - start_tv.tv_usec) / 1000L;
4266 +# endif
4267 + if (wtime < 0)
4268 + return 0;
4271 + else if (rc == 0)
4272 + return 0;
4273 + else
4274 + goto close;
4277 + /* read the data */
4278 + if ((len = read(this->fd, (char *)buff, size - 1)) < 0)
4279 + goto close;
4281 + buff[len] = NUL;
4282 + return len;
4283 +close:
4284 + gdb_close(this);
4285 + return -1;
4288 +/* Free a bpinfo_T list and set address referenced by plist to NULL */
4289 + void
4290 +gdb_free_bplist (plist)
4291 + bpinfo_T ** plist;
4293 + bpinfo_T *p, *next;
4295 + if (plist == NULL)
4296 + return;
4298 + for (p = *plist; p != NULL; p = next)
4300 + gdb_undefine_sign(p->typenr);
4301 + next = p->next;
4302 + xfree(p);
4305 + *plist = NULL;
4308 +/* Remove str from input history */
4309 + static void
4310 +histdel(str)
4311 + char_u *str; /* string to remove */
4313 + char_u *pat;
4314 + char_u *res;
4316 + if (str != NULL && (res = vim_strsave_escaped(str, (char_u *)"\\")) != NULL)
4318 + /* nomagic: only the backslash has a special meaning */
4319 + pat = NULL;
4320 + gdb_cat(&pat, (char_u *)"\\V\\^");
4321 + gdb_cat(&pat, res);
4322 + gdb_cat(&pat, (char_u *)"\\$");
4324 + (void)del_history_entry(HIST_INPUT, pat);
4325 + xfree(pat);
4327 + xfree(res);
4331 +/* Get the GDB command type */
4332 + void
4333 +gdb_cmd_type(this, cmd)
4334 + gdb_T *this;
4335 + char_u *cmd;
4337 + regmatch_T regmatch;
4338 + token_T *tok;
4340 + regmatch.rm_ic = FALSE; /* always match case */
4341 + this->cmd_type = CMD_ANY;
4342 + for (tok = tokens; tok->keyword != NULL; tok++)
4343 + if ((regmatch.regprog = tok->regprog) != NULL
4344 + && vim_regexec(&regmatch, cmd, (colnr_T)0))
4346 + this->cmd_type = tok->type;
4347 + break;
4352 + * Append src to string pointed to by pdest or copy src to a new allocated
4353 + * string when *pdest is NULL.
4354 + * *pdest is reallocated to make room for src.
4355 + * Append an empty string when src is NULL.
4356 + */
4357 + void
4358 +gdb_cat(pdest, src)
4359 + char_u **pdest; /* string address to append to */
4360 + char_u *src; /* string to append */
4362 + int ldest = (*pdest != NULL ? STRLEN(*pdest) : 0);
4363 + int lsrc = (src != NULL ? STRLEN(src) : 0);
4364 + char_u *res;
4366 + if (lsrc != 0 || *pdest == NULL)
4368 + res = (char_u *)xmalloc(ldest + lsrc + 1);
4370 + if (ldest == 0)
4372 + if (lsrc != 0)
4373 + STRCPY(res, src);
4374 + else
4375 + STRCPY(res, "");
4377 + else
4379 + STRCPY(res, *pdest);
4380 + STRCAT(res, src); /* assert src != NULL */
4383 + xfree(*pdest);
4384 + *pdest = res;
4389 + * Return an allocated string that is the sub-match indexed by subid ([0-9])
4390 + * using compiled pattern id.
4391 + * Return NULL if str does not match (or no such sub-match in pattern).
4392 + */
4393 + char_u *
4394 +gdb_regexec(str, id, subid, obs)
4395 + char_u *str; /* string to match against */
4396 + int id; /* pattern id */
4397 + int subid; /* sub-match index */
4398 + struct obstack *obs;/* obstack to use for allocating memory */
4400 + pattern_T *pat;
4401 + regmatch_T regmatch;
4403 + if (str == NULL || *str == NUL || subid < 0 || subid > 9)
4404 + return NULL;
4406 + for (pat = patterns; pat->str != NULL; pat++)
4407 + if (pat->id == id)
4409 + regmatch.rm_ic = FALSE; /* always match case */
4410 + if ((regmatch.regprog = pat->regprog) != NULL
4411 + && vim_regexec(&regmatch, str, (colnr_T)0)
4412 + && regmatch.startp[subid] != NULL)
4414 + if (obs != NULL)
4415 + return (char_u *)obstack_copy0(obs, regmatch.startp[subid],
4416 + (int)(regmatch.endp[subid] - regmatch.startp[subid]));
4417 + else
4418 + return (char_u *)clewn_strnsave((char *)regmatch.startp[subid],
4419 + (int)(regmatch.endp[subid] - regmatch.startp[subid]));
4421 + break;
4423 + return NULL;
4426 +/* Return an integer as a string */
4427 + char_u *
4428 +gdb_itoa(i)
4429 + int i; /* integer to stringify */
4431 + static char buf[NUMBUFLEN];
4433 + sprintf(buf, "%ld", (long)i);
4434 + return (char_u *)buf;
4436 +#endif /* FEAT_GDB */
4438 Property changes on: src/gdb.c
4439 ___________________________________________________________________
4440 Name: svn:keywords
4441 + Id
4444 Property changes on: src
4445 ___________________________________________________________________
4446 Name: svn:ignore
4447 + objects
4449 clewn
4450 config.log
4452 tags
4455 diff -c --new-file old/clewn/gdb.h src/clewn/gdb.h
4456 *** old/clewn/gdb.h 1970-01-01 01:00:00.000000000 +0100
4457 --- src/clewn/gdb.h 2007-07-21 18:35:40.000000000 +0200
4458 ***************
4459 *** 0 ****
4460 --- 1,685 ----
4461 + /* vi:set ts=8 sts=4 sw=4:
4463 + * Copyright (C) 2004 Xavier de Gaye.
4465 + * This program is free software; you can redistribute it and/or modify
4466 + * it under the terms of the GNU General Public License as published by
4467 + * the Free Software Foundation; either version 2, or (at your option)
4468 + * any later version.
4470 + * This program is distributed in the hope that it will be useful,
4471 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4472 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4473 + * GNU General Public License for more details.
4475 + * You should have received a copy of the GNU General Public License
4476 + * along with this program (see the file COPYING); if not, write to the
4477 + * Free Software Foundation, Inc.,
4478 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
4480 + * $Id: gdb.h 148 2007-07-21 16:35:40Z xavier $
4481 + */
4483 + #ifndef GDB_H
4484 + # define GDB_H
4486 + #define obstack_chunk_alloc malloc
4487 + #define obstack_chunk_free free
4488 + #define obstack_strsave(o,s) (char_u *)obstack_copy0((o), (s), STRLEN((s)))
4489 + #define obstack_strcat(o,s) \
4490 + ( (s) ? obstack_grow((o), (s), STRLEN((s))) : 0)
4491 + #define obstack_strcat0(o,s) \
4492 + ( (s) \
4493 + ? obstack_grow0((o), (s), STRLEN((s))) \
4494 + : obstack_grow0((o), "", 0))
4496 + #define GDB_LVL2_SUPPORT
4497 + #define GDB_LVL3_SUPPORT
4498 + /*#define GDB_MI_SUPPORT */
4500 + /* |+gdb| modes */
4501 + #define GDB_MODE_LVL2 1 /* CLI with annotations level 2 */
4502 + #define GDB_MODE_LVL3 2 /* CLI with annotations level 3 and GDB/MI */
4503 + #define GDB_MODE_MI 3 /* GDB/MI */
4505 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4506 + /*
4507 + * GDB does not send ANO_BP_INVALID annotation when hitting a breakpoint
4508 + * that has been 'enable once'.
4509 + * Undefine BP_INVALID_ANO_MISSING after GDB fixes this
4510 + */
4511 + # define BP_INVALID_ANO_MISSING
4512 + #endif
4514 + #define KEY_INTERUPT Ctrl_Z /* interrupt */
4515 + #define MAX_BUFFSIZE 1024
4517 + /* The breakpoint info record structure */
4518 + typedef struct bpinfo_struct bpinfo_T;
4520 + struct bpinfo_struct
4522 + int id; /* breakpoint number */
4523 + int typenr; /* sign type number, for Clewn: sequence sign type number in this buffer */
4524 + #ifdef BP_INVALID_ANO_MISSING
4525 + int disposition; /* TRUE when keep, FALSE when disabled */
4526 + #endif
4527 + int enabled; /* TRUE when enabled */
4528 + int cont; /* TRUE when 'commands' includes continue */
4529 + #ifdef FEAT_GDB
4530 + buf_T *buf; /* breakpoint buffer */
4531 + #else
4532 + int buf; /* Clewn buffer number */
4533 + int typenr_en; /* enabled breakpoint sequence number */
4534 + int typenr_dis; /* disabled breakpoint sequence number */
4535 + #endif
4536 + linenr_T lnum; /* breakpoint line number */
4537 + bpinfo_T *next;
4538 + };
4540 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4541 + /* Annotation types */
4542 + # define ANO_NONE 0
4543 + # define ANO_ANY 1 /* some unrecognized annotation */
4545 + /* level 2 and level 3 annotations */
4546 + # define ANO_PREPROMPT 101
4547 + # define ANO_PROMPT 102
4548 + # define ANO_POSTPROMPT 103
4549 + # define ANO_PRECMDS 104
4550 + # define ANO_CMDS 105
4551 + # define ANO_PREOVERLOAD 106
4552 + # define ANO_OVERLOAD 107
4553 + # define ANO_PREQUERY 108
4554 + # define ANO_QUERY 109
4555 + # define ANO_PREPMT_FORMORE 110
4556 + # define ANO_PMT_FORMORE 111
4557 + # define ANO_POSTPMT_FORMORE 112
4558 + # define ANO_QUIT 113
4559 + # define ANO_ERROR_BEG 114
4560 + # define ANO_FRAME_INVALID 115
4561 + # define ANO_BP_INVALID 116
4562 + # define ANO_STARTING 117
4563 + # define ANO_STOPPED 118
4564 + # define ANO_EXITED 119
4565 + # define ANO_SIGNALLED 120
4566 + # define ANO_BREAKPOINT 121
4567 + # define ANO_SOURCE 122
4569 + # define KEY_KILL Ctrl_U /* readline 'unix-line-discard' */
4570 + # define LPP_LINES 500 /* large output interruption interval */
4572 + /* Command completion states */
4573 + # define CS_START 0
4574 + # define CS_PENDING 1
4575 + # define CS_CHOICE 2
4576 + # define CS_DONE 3
4577 + # define CS_QUERY 4
4579 + /* The gdb CLI cmd */
4580 + typedef struct
4582 + int state; /* cmd completion state */
4583 + int cnt; /* lines output by gdb since last cmd */
4584 + char_u *gdb; /* partial cmd sent to gdb */
4585 + char_u *readline; /* gdb readline content */
4586 + char_u *echoed; /* echoed cmd */
4587 + } cli_cmd_T;
4589 + /* breakpoint states */
4590 + # define BPS_INVALID 0x0100 /* got "breakpoints-invalid" annotation */
4591 + # define BPS_BP_HIT 0x0200 /* got "breakpoint" annotation */
4592 + # define BPS_FR_INVALID 0x0400 /* got "frames-invalid" annotation */
4593 + # define BPS_BP_SET 0x0800 /* a break type GDB cmd is being processed */
4594 + # define BPS_RECORD 0x1000 /* parsing a record in the breakpoint table */
4595 + # define BPS_START 0x2000 /* start of a record */
4596 + #endif /* defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT) */
4598 + #ifdef GDB_LVL2_SUPPORT
4599 + /* level 2 annotations */
4600 + # define ANO_FRAME_BEGIN 201
4601 + # define ANO_FRAME_END 202
4602 + # define ANO_BP_HEADER 203
4603 + # define ANO_BP_TABLE 204
4604 + # define ANO_BP_RECORD 205
4605 + # define ANO_BP_FIELD0 206 /* Number */
4606 + # define ANO_BP_FIELD1 207 /* Type */
4607 + # define ANO_BP_FIELD2 208 /* Disposition */
4608 + # define ANO_BP_FIELD3 209 /* Enable */
4609 + # define ANO_BP_FIELD4 210 /* Address */
4610 + # define ANO_BP_FIELD5 211 /* What */
4611 + # define ANO_BP_FIELD6 212 /* Frame */
4612 + # define ANO_BP_FIELD7 213 /* Condition */
4613 + # define ANO_BP_FIELD8 214 /* Ignore-count */
4614 + # define ANO_BP_FIELD9 215 /* Commands */
4615 + # define ANO_BP_END 216
4616 + # define ANO_DISP_BEG 217
4617 + # define ANO_DISP_NUMEND 218
4618 + # define ANO_DISP_FMT 219
4619 + # define ANO_DISP_EXP 220
4620 + # define ANO_DISP_EXPEND 221
4621 + # define ANO_DISP_VALUE 222 /* not output by GDB */
4622 + # define ANO_DISP_END 223
4623 + # define ANO_FIELD_BEG 224
4624 + # define ANO_FIELD_NAMEND 225
4625 + # define ANO_FIELD_VALUE 226
4626 + # define ANO_FIELD_END 227
4627 + # define ANO_ARRAY_BEG 228
4628 + # define ANO_ARRAY_ELT 229
4629 + # define ANO_ARRAY_ELTREP 230
4630 + # define ANO_ARRAY_ELTEND 231
4631 + # define ANO_ARRAY_END 232
4633 + /* breakpoints */
4634 + # define IS_RECORD(s) ((s) & BPS_RECORD)
4635 + # define RECORD_INDEX(s) ((s) & 0xff)
4636 + # define SET_RECORD_IDX(s, i) (((s) & ~0xff) | (i))
4638 + /* breakpoint annotation fields indexes */
4639 + # define BI_NUM 0
4640 + # define BI_TYPE 1
4641 + # define BI_DISPO 2
4642 + # define BI_ENABLE 3
4643 + # define BI_ADDRESS 4
4644 + # define BI_WHAT 5
4645 + # define BI_FRAME 6
4646 + # define BI_COND 7
4647 + # define BI_COUNT 8
4648 + # define BI_CMMDS 9 /* commands */
4649 + # define BI_FIELDS 10 /* number of bp info annotation fields */
4651 + /* The display object structure */
4652 + typedef struct gdbdisp_struct gdbdisp_T;
4654 + struct gdbdisp_struct
4656 + int num; /* display number */
4657 + int state; /* highlighted or/and changed */
4658 + gdbdisp_T * next;
4659 + };
4661 + /* display states */
4662 + # define DSP_INIT 0
4663 + # define DSP_STOPPED 1
4665 + /* The display list structure */
4666 + typedef struct
4668 + int state;
4669 + gdbdisp_T * list;
4670 + } displist_T;
4672 + /* The display entry structure used to store a GDB display output */
4673 + typedef struct
4675 + char_u * num; /* display item number */
4676 + char_u * expression;/* display item format and expression */
4677 + char_u * value; /* display item value */
4678 + } doutput_T;
4680 + /* The lvl2 mode structure: lvl2 specific data */
4681 + typedef struct
4683 + /* breakpoints */
4684 + char_u *info[BI_FIELDS]; /* breakpoint info record contents */
4686 + /* variables (display) window */
4687 + displist_T varlist; /* list of display items */
4688 + doutput_T dentry; /* current GDB display output entry */
4689 + int doing_value; /* when TRUE: currently handling a display value */
4690 + char_u *dispinfostr;/* current line output after "info display" */
4691 + char_u *dispinfo; /* all item numbers result of a "info display" */
4692 + } lvl2_T;
4693 + #endif /* GDB_LVL2_SUPPORT */
4695 + #ifdef GDB_LVL3_SUPPORT
4696 + /* The variable object structure */
4697 + typedef struct varobj_struct varobj_T;
4699 + /* varobj states */
4700 + #define VS_INIT 0x01 /* object creation */
4701 + #define VS_ERROR 0x02 /* a command on this object produced an error */
4703 + struct varobj_struct
4705 + int state;
4706 + char_u *name; /* variable name ("NNN" in "varNNN") */
4707 + int children; /* TRUE when has children */
4708 + char_u *format; /* print format is "/[tdxo]"*/
4709 + char_u *expression; /* variable expression */
4710 + varobj_T * next;
4711 + };
4713 + /* GDB/MI var commands */
4714 + # define VCMD_INIT 0
4715 + # define VCMD_CREATE 1
4716 + # define VCMD_DELETE 2
4717 + # define VCMD_CHILDREN 3
4718 + # define VCMD_UPDATE 4
4719 + # define VCMD_PRINT 5
4720 + # define VCMD_EVALUATE 6
4721 + # define VCMD_FORMAT 7
4723 + /* The lvl3 mode structure: lvl3 specific data */
4724 + typedef struct
4726 + char_u *result; /* result of a GDB/MI command */
4728 + int get_source_list;
4729 + char_u *source_cur; /* result of -file-list-exec-source-file */
4730 + char_u *source_list;/* result of -file-list-exec-source-files */
4732 + /* variables window */
4733 + varobj_T *varlist; /* list of variable objects */
4734 + varobj_T *varitem; /* current object in varlist */
4735 + int varcmd; /* GDB/MI var cmd being processed */
4736 + int varnext_cmd; /* GDB/MI var next cmd to process */
4737 + } lvl3_T;
4738 + #endif /* GDB_LVL3_SUPPORT */
4740 + /* Command types */
4741 + #define CMD_ANY 0
4742 + #ifdef FEAT_GDB
4743 + # define CMD_DIR 1
4744 + #endif
4745 + #define CMD_DETACH 2
4746 + #define CMD_SHELL 3
4747 + #define CMD_STEPI 4 /* instruction stepping cmds */
4748 + #define CMD_EXECF 5 /* invalidating asm buffers cmds */
4749 + #define CMD_BREAK 6
4750 + #define CMD_DISPLAY 7
4751 + #define CMD_CREATEVAR 8
4752 + #define CMD_UP 9
4753 + #define CMD_DOWN 10
4754 + #define CMD_FRAME 11
4755 + #define CMD_DISABLE 12
4756 + #define CMD_DELETE 13
4757 + #define CMD_UP_SILENT 14
4758 + #define CMD_DOWN_SILENT 15
4759 + #define CMD_SLECT_FRAME 16
4760 + #define CMD_SYMF 17
4761 + #define CMD_RESTART 18
4762 + #define CMD_QUIT 19
4764 + #define ASM_MAX_BUFF 64 /* asm buffers pool size */
4765 + #define ASM_BUF_NAME "gdb-asm-" /* asm buffer name prefix */
4766 + #define ASM_OLD (char_u)(~0U) /* asm buffer max age */
4768 + /* The assembly buffer pool */
4769 + typedef struct
4771 + #ifdef FEAT_GDB
4772 + int max; /* buffers in use */
4773 + int idx; /* current buffer */
4774 + buf_T * buf[ASM_MAX_BUFF]; /* asm buffers */
4775 + char_u age[ASM_MAX_BUFF]; /* buffer's age */
4776 + int last; /* used for generating unique asm names */
4777 + #else
4778 + int buf; /* number of the asm buffer being disassembled */
4779 + FILE *fd; /* stream descriptor of asm file being written to */
4780 + char_u *name; /* file name of the function being disassembled */
4781 + long line_offset; /* offset of start of last line in file */
4782 + #endif
4783 + linenr_T lnum; /* highlited line number */
4784 + int hilite; /* TRUE when $pc in asm is highlited */
4785 + } asm_T;
4787 + /* The gdb structure */
4788 + typedef struct gdb_struct gdb_T;
4790 + /* Out of band states */
4791 + #define OS_CMD 0x01 /* a cmd is being processed */
4792 + #define OS_INTR 0x02 /* interrupt sent to gdb */
4793 + #define OS_QUIT 0x04 /* 'quit' annotation received */
4795 + /* Out of Band */
4796 + #define OOB_CMD 0
4797 + #define OOB_COLLECT 1
4798 + #define OOB_COMPLETE 2
4799 + #define IS_OOBACTIVE(t) (((t)->oob.idx) >= 0)
4801 + /* The out of band process */
4802 + typedef struct
4804 + int state; /* oob state */
4805 + int idx; /* current function index */
4806 + int cnt; /* asm output lines count */
4807 + } oob_T;
4809 + /*
4810 + * oobfunc_T function:
4812 + * When an oobfunc_T[] array is processed by gdb_oob_send() and
4813 + * gdb_oob_receive(), each oob function in the array is called with
4814 + * successive state values of:
4816 + * OOB_CMD: called at each 'prompt'; should return the GDB cmd
4817 + * to send to GDB or NULL when no command must be sent;
4818 + * in this case the next oob function in the oobfunc_T[]
4819 + * array is processed next with OOB_CMD
4821 + * OOB_COLLECT: oob may process chunk, a (possibly partial) line from GDB
4822 + * result of GDB command; may be invoked more than once, or not at all
4824 + * OOB_COMPLETE:indicates end of GDB output; oob may do any final processing;
4825 + * if oob returns a non NULL value, the same oob function is
4826 + * called once again with OOB_CMD and the same cycle starts again;
4827 + * if oob returns a NULL value, the next oob function in the
4828 + * oobfunc_T[] array is processed with OOB_CMD
4830 + * Return: NULL, except when state is OOB_CMD or OOB_COMPLETE
4831 + */
4833 + typedef struct {
4834 + char * (*oob)(gdb_T *, int state, char_u *chunk, struct obstack *);
4835 + } oobfunc_T;
4837 + /* gdb states */
4838 + #define GDB_STATE(i,s) (((i) != NULL) ? ((((gdb_T *)(i))->state) & (s)):FALSE)
4839 + #define GS_INIT 0 /* initial state */
4840 + #define GS_CLOSING 0x001 /* gdb process closing */
4841 + #define GS_UP 0x002 /* gdb up and running */
4842 + #define GS_STARTED 0x004 /* gdb just started */
4843 + #define GS_ALLOWED 0x008 /* select on pty is allowed */
4844 + #define GS_EVENT 0x010 /* got SIGCHLD or gdb output some data */
4845 + #define GS_SIGCHLD 0x020 /* got SIGCHLD from gdb */
4846 + #define GS_STOPPED 0x040 /* debuggee is stopped */
4847 + #define GS_ANO 0x080 /* parsing an annotation table or list */
4848 + #define GS_QUITTING 0x100 /* quitting clewn */
4850 + /* parser states */
4851 + #define PS_ANY 0
4852 + #define PS_PREPROMPT 1 /* before the prompt, after any output from GDB */
4853 + #define PS_PROMPT 2 /* after prompt, but before user input */
4855 + /* project file sourced states */
4856 + #define PROJ_INIT 0
4857 + #define PROJ_SOURCEIT 1
4858 + #define PROJ_DONE 2
4860 + /* The gdb structure */
4861 + struct gdb_struct
4863 + /* process */
4864 + int instance; /* gdb instance number */
4865 + int fd; /* pty file descriptor */
4866 + pid_t pid; /* process id */
4867 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4868 + int height; /* pseudo tty height, non zero when ioctl set */
4869 + int intr_sent; /* hack: an interrupt has been sent by the user */
4870 + #endif
4871 + int state; /* gdb state */
4872 + char_u *status; /* gdb status */
4873 + int recurse; /* disable GS_ALLOWED when calling safe_vgetc */
4875 + /* cmds */
4876 + int cmd_type; /* cmd type */
4877 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4878 + cli_cmd_T cli_cmd; /* current CLI cmd (common to lvl2 and lvl3) */
4879 + #endif
4880 + char_u *firstcmd; /* first cmd in new GDB session */
4881 + int parser; /* parser states */
4882 + int syntax; /* when TRUE, enable syntax highlighting */
4883 + char_u *line; /* last incomplete line */
4884 + char_u *winput_cmd; /* cmd inserted in input-line window */
4885 + char_u *directories;/* gdb search path for source files */
4886 + #ifndef FEAT_GDB
4887 + char_u *prompt; /* the current GDB prompt */
4888 + char * version; /* clewn version */
4889 + char_u * pwd; /* current working directory */
4890 + char_u * args; /* debugge command line arguments */
4891 + #endif
4892 + char_u *sfile; /* symbol file name */
4894 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4895 + /* annotations */
4896 + int note; /* annotation type */
4897 + int annoted; /* TRUE when parsing an annotation */
4898 + int newline; /* pending NL, possibly an annotation first char */
4899 + int valid_note; /* last non prompt-for-more annotation type */
4900 + int prev_note; /* previous annotation type */
4901 + char_u *annotation; /* last incomplete annotation */
4902 + #endif
4904 + /* disassembly */
4905 + asm_T pool; /* asm buffers pool */
4906 + char_u *pc; /* program counter where debuggee is stopped */
4907 + char_u *frame_pc; /* current frame program counter */
4908 + char_u *oob_result; /* result of oob gdb_get_frame */
4909 + char_u *asm_add; /* address whose function must be disassembled */
4910 + char_u *asm_func; /* asm function name */
4912 + /* breakpoints */
4913 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4914 + int bp_state; /* breakpoint annotation state (and index) */
4915 + bpinfo_T *tmplist; /* tmp new bp list when reading "info beakpoints" */
4916 + #endif
4917 + bpinfo_T *record; /* current record */
4918 + int bufIsChanged; /* TRUE when curbuf is changed after edit failed */
4919 + int cont; /* TRUE when pgm is continuing at this bp */
4920 + bpinfo_T *bpinfo; /* breakpoints info table */
4921 + int frame_curlvl; /* current frame level */
4922 + linenr_T frame_lnum;/* current frame line number */
4923 + char_u * frame_fname;/* current frame file name */
4925 + #ifdef FEAT_GDB
4926 + buf_T *buf; /* gdb buffer */
4927 + buf_T *fr_buf; /* frame sign buffer */
4928 + buf_T *var_buf; /* variables window buffer */
4929 + #else /* Clewn implementation */
4930 + linenr_T lastline; /* lastline being disassembled */
4931 + int fr_buf; /* frame sign buffer number */
4932 + linenr_T lnum; /* frame sign line number */
4933 + int var_buf; /* variables buffer number */
4934 + char_u *var_name; /* variables file name */
4935 + char_u *balloon_txt;/* text over which is pointed the mouse */
4936 + char * project_file;/* project file name */
4937 + int project_state; /* project file sourced state */
4938 + #endif
4939 + oob_T oob; /* out of band data */
4941 + /* |+gdb| modes */
4942 + int mode; /* current |+gdb| mode */
4943 + #ifdef GDB_LVL2_SUPPORT
4944 + lvl2_T lvl2; /* annotations level 2 */
4945 + #endif
4946 + #ifdef GDB_LVL3_SUPPORT
4947 + lvl3_T lvl3; /* annotations level 3 and GDB/MI */
4948 + #endif
4950 + /* pointers to mode specific functions */
4951 + oobfunc_T *oobfunc; /* the current oob functions array */
4952 + oobfunc_T *std_oobfunc; /* the standard oob functions array */
4953 + int (*parse_output)(gdb_T *); /* parser function */
4954 + void (*gdb_docmd)(gdb_T *, char_u *);/* GDB command input function */
4955 + void (*var_delete)(gdb_T *); /* delete all variables function */
4956 + void (*clear_gdb_T)(gdb_T *); /* clear mode specific stuff */
4957 + };
4959 + /* Regexp patterns */
4960 + #define PAT_DIR 1
4961 + #define PAT_CHG_ANNO 2
4962 + #define PAT_ADD 3
4963 + #define PAT_PID 4
4965 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4966 + # define PAT_SOURCE 101
4967 + # define PAT_QUERY 102
4968 + # define PAT_YES 103
4969 + # define PAT_SFILE 104
4970 + # define PAT_BP_CONT 105
4971 + # define PAT_ASM_FUNC 106
4972 + # define PAT_ASM_FUNC_P 107
4973 + # define PAT_FRAME 108
4974 + # define PAT_HEIGHT 109
4975 + #endif
4977 + #ifdef GDB_LVL2_SUPPORT
4978 + # define PAT_BP_ASM 201
4979 + # define PAT_BP_SOURCE 202
4980 + # define PAT_DISPLAY 203
4981 + # define PAT_DISPINFO 204
4982 + # define PAT_CREATEVAR 205
4983 + #endif
4985 + # ifdef GDB_LVL3_SUPPORT
4986 + # define PAT_CRVAR_FMT 301
4987 + # define PAT_INFO_FRAME 302
4988 + #endif
4990 + /* User interface */
4991 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4992 + void gdb_docmd_cli __ARGS((gdb_T *, char_u *));
4993 + void gdb_send_cmd __ARGS((gdb_T *, char_u *));
4994 + #endif
4996 + /* Vim low level hook */
4997 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
4998 + int gdb_parse_output_cli __ARGS((gdb_T *));
4999 + #endif
5001 + /* Gdb process mgmt */
5002 + void gdb_close __ARGS((gdb_T *));
5003 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
5004 + int gdb_setup_cli __ARGS((gdb_T *));
5005 + #endif
5007 + /* Gdb mode initialization */
5008 + #ifdef GDB_LVL2_SUPPORT
5009 + void gdb_lvl2_init __ARGS((gdb_T *));
5010 + #endif
5011 + #ifdef GDB_LVL3_SUPPORT
5012 + void gdb_lvl3_init __ARGS((gdb_T *));
5013 + #endif
5015 + /* Sign highliting */
5016 + #define FRAME_SIGN 1
5017 + #ifdef FEAT_GDB
5018 + # define PHANTOM_SIGN 2
5019 + # define BP_SIGN_ID(n) ((n)+2) /* reserved sign ids: 1 frame, 2 phantom */
5020 + void gdb_fr_lite __ARGS((gdb_T *, buf_T *, linenr_T, struct obstack *));
5021 + int gdb_define_sign __ARGS((int, int));
5022 + void gdb_undefine_sign __ARGS((int));
5023 + buf_T * gdb_unlite __ARGS((int));
5024 + #else
5025 + # define BP_SIGN_ID(n) ((n)+1) /* reserved sign id: 1 frame */
5026 + void gdb_fr_lite __ARGS((gdb_T *, int, linenr_T, struct obstack *));
5027 + int gdb_define_bpsign __ARGS((bpinfo_T *, struct obstack *));
5028 + void gdb_unlite __ARGS((int));
5029 + #endif
5030 + int gdb_as_frset __ARGS((gdb_T *, struct obstack *));
5031 + int gdb_fr_set __ARGS((gdb_T *, char_u *, linenr_T *, struct obstack *));
5032 + void gdb_fr_unlite __ARGS((gdb_T *));
5034 + /* Window and buffer mgmt */
5035 + #ifdef FEAT_GDB
5036 + win_T *gdb_btowin __ARGS((buf_T *));
5037 + void gdb_as_setname __ARGS((char_u *));
5038 + void gdb_clear_asmbuf __ARGS((gdb_T *, buf_T *));
5039 + win_T * gdb_edit_file __ARGS((gdb_T *, buf_T *, char_u *, linenr_T, struct obstack *));
5040 + void gdb_set_cursor __ARGS((win_T *, linenr_T));
5041 + void gdb_popup_console __ARGS((gdb_T *));
5042 + void gdb_redraw __ARGS((buf_T *));
5043 + #else
5044 + int gdb_edit_file __ARGS((int, char_u *, linenr_T, int, struct obstack *));
5045 + #endif
5046 + void gdb_msg_busy __ARGS((char_u *));
5047 + void gdb_showBalloon __ARGS((char_u *, struct obstack *));
5048 + void gdb_status __ARGS((gdb_T *, char_u *, struct obstack *));
5049 + void gdb_write_buf __ARGS((gdb_T *, char_u *, int));
5051 + /* Out Of Band */
5052 + void gdb_oob_send __ARGS((gdb_T *, struct obstack *));
5053 + void gdb_oob_receive __ARGS((gdb_T *, char_u *, struct obstack *));
5054 + #if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
5055 + char * gdb_print_value __ARGS((gdb_T *, int, char_u *, struct obstack *));
5056 + char * gdb_get_pc __ARGS((gdb_T *, int, char_u *, struct obstack *));
5057 + char * gdb_get_frame __ARGS((gdb_T *, int, char_u *, struct obstack *));
5058 + char * gdb_info_frame __ARGS((gdb_T *, int, char_u *, struct obstack *));
5059 + char * gdb_stack_frame __ARGS((gdb_T *, int, char_u *, struct obstack *));
5060 + char * gdb_get_sfile __ARGS((gdb_T *, int, char_u *, struct obstack *));
5061 + #ifndef FEAT_GDB
5062 + char * gdb_source_project __ARGS((gdb_T *, int, char_u *, struct obstack *));
5063 + char * gdb_get_pwd __ARGS((gdb_T *, int, char_u *, struct obstack *));
5064 + char * gdb_get_args __ARGS((gdb_T *, int, char_u *, struct obstack *));
5065 + #endif
5066 + char * gdb_source_cur __ARGS((gdb_T *, int, char_u *, struct obstack *));
5067 + char * gdb_source_list __ARGS((gdb_T *, int, char_u *, struct obstack *));
5068 + char * gdb_get_sourcedir __ARGS((gdb_T *, int, char_u *, struct obstack *));
5069 + char * gdb_get_asmfunc __ARGS((gdb_T *, int, char_u *, struct obstack *));
5070 + char * gdb_get_asmfunc_hack __ARGS((gdb_T *, int, char_u *, struct obstack *));
5071 + char * gdb_get_asm __ARGS((gdb_T *, int, char_u *, struct obstack *));
5072 + void gdb_process_record __ARGS((gdb_T *, char_u *, char_u *, char_u *, char_u *, struct obstack *));
5073 + #endif
5075 + /* Variables window management */
5076 + #ifdef GDB_LVL2_SUPPORT
5077 + void gdb_process_display __ARGS((gdb_T *, char_u *, struct obstack *));
5078 + #endif
5080 + /* Utilities */
5081 + #ifndef MIN
5082 + #define MIN(a,b) (((a)<(b))?(a):(b))
5083 + #endif
5084 + #ifndef ABS
5085 + #define ABS(x) (((x)<0)?(-(x)):(x))
5086 + #endif
5087 + #define STRCHR(s,c) (char_u *)strchr((char *)(s),(int)(c))
5088 + #define STRSTR(h,n) (char_u *)strstr((char *)(h),(char *)(n))
5089 + #define FREE(p) {xfree((p)); (p) = NULL;}
5090 + #define IS_ANNOTATION(l) (STRSTR((l),"\032\032") == (l))
5091 + #define BUFLASTL(b) (!(((b)->b_ml.ml_flags) & ML_EMPTY)?((b)->b_ml.ml_line_count):0)
5092 + int gdb_read __ARGS((gdb_T *, char_u *, int, int));
5093 + void gdb_free_bplist __ARGS((bpinfo_T **));
5094 + void gdb_cmd_type __ARGS((gdb_T *, char_u *));
5095 + void gdb_cat __ARGS((char_u **, char_u *));
5096 + char_u * gdb_regexec __ARGS((char_u *, int, int, struct obstack *));
5097 + char_u * gdb_itoa __ARGS((int));
5099 + /* Gdb memory leaks mtrace */
5100 + #if defined(GDB_MTRACE) && defined(HAVE_MTRACE)
5101 + # include <malloc.h>
5102 + # include <mcheck.h>
5103 + /* storage for mtrace hooks */
5104 + extern __ptr_t (*s_malloc) (size_t, const void *);
5105 + extern void (*s_free) (void *, const void *);
5106 + extern __ptr_t (*s_realloc) (void *, size_t, const void *);
5108 + # define mv_hooks() do { \
5109 + s_malloc = __malloc_hook; \
5110 + s_free = __free_hook; \
5111 + s_realloc = __realloc_hook; \
5112 + __malloc_hook = NULL; \
5113 + __free_hook = NULL; \
5114 + __realloc_hook = NULL; \
5115 + } while (0)
5117 + # define get_hooks() do { \
5118 + __malloc_hook = s_malloc; \
5119 + __free_hook = s_free; \
5120 + __realloc_hook = s_realloc; \
5121 + } while (0)
5123 + /* we do call sometimes vim_free directly and allocation is not mtraced:
5124 + * when the called Vim function does not free all its allocated memory
5125 + * after it returns */
5126 + # define xmalloc(s) ({char_u *mret; get_hooks(); mret=xmalloc((s)); mv_hooks(); mret;})
5127 + # define xcalloc(s) ({char_u *mret; get_hooks(); mret=xcalloc((s)); mv_hooks(); mret;})
5128 + # define xrealloc(m,s) ({char_u *mret; get_hooks(); mret=xrealloc((m),(s)); mv_hooks(); mret;})
5130 + # define xfree(x) do { \
5131 + get_hooks(); \
5132 + xfree((x)); \
5133 + mv_hooks(); \
5134 + } while (0)
5136 + # define clewn_strsave(s) ({char_u *mret; get_hooks(); mret=clewn_strsave((s)); mv_hooks(); mret;})
5137 + # define clewn_strnsave(s,l) ({char_u *mret; get_hooks(); mret=clewn_strnsave((s),(l)); mv_hooks(); mret;})
5139 + # define vim_strsave_escaped(s,e) ({char_u *mret; get_hooks(); mret=vim_strsave_escaped((s),(e)); mv_hooks(); mret;})
5140 + # define vim_regcomp(s,m) ({regprog_T *mret; get_hooks(); mret=vim_regcomp((s),(m)); mv_hooks(); mret;})
5141 + # define FullName_save(n,f) ({char_u *mret; get_hooks(); mret=FullName_save((n),(f)); mv_hooks(); mret;})
5142 + # define get_option_value(n,u,s,o) ({int r; get_hooks(); r=get_option_value((n),(u),(s),(o)); mv_hooks(); r;})
5143 + #endif /* GDB_MTRACE */
5144 + #endif /* GDB_H */
5146 diff -c --new-file old/clewn/gdb_lvl2.c src/clewn/gdb_lvl2.c
5147 *** old/clewn/gdb_lvl2.c 1970-01-01 01:00:00.000000000 +0100
5148 --- src/clewn/gdb_lvl2.c 2008-10-13 16:38:07.000000000 +0200
5149 ***************
5150 *** 0 ****
5151 --- 1,1085 ----
5152 + /* vi:set ts=8 sts=4 sw=4:
5154 + * Copyright (C) 2004 Xavier de Gaye.
5156 + * This program is free software; you can redistribute it and/or modify
5157 + * it under the terms of the GNU General Public License as published by
5158 + * the Free Software Foundation; either version 2, or (at your option)
5159 + * any later version.
5161 + * This program is distributed in the hope that it will be useful,
5162 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5163 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5164 + * GNU General Public License for more details.
5166 + * You should have received a copy of the GNU General Public License
5167 + * along with this program (see the file COPYING); if not, write to the
5168 + * Free Software Foundation, Inc.,
5169 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
5171 + * $Id: gdb_lvl2.c 222 2008-10-13 14:38:07Z xavier $
5172 + */
5174 + # ifdef HAVE_CLEWN
5175 + # include <config.h>
5176 + # include "obstack.h"
5177 + # include "clewn.h"
5178 + # else
5179 + # include "vim.h"
5180 + # include "clewn/obstack.h"
5181 + # endif
5183 + #if defined(FEAT_GDB) || defined(HAVE_CLEWN)
5185 + # include "gdb.h"
5186 + # include "misc.h"
5188 + # ifdef GDB_LVL2_SUPPORT
5190 + /* display item states */
5191 + # define DISP_CHANGED 0x01 /* item expression value has changed */
5192 + # define DISP_HILITED 0x02 /* item expression value is hilited */
5194 + /* Gdb process mgmt */
5195 + static void clear_gdb_T __ARGS((gdb_T *));
5197 + /* Out Of Band */
5198 + static char *get_lastbp __ARGS((gdb_T *, int, char_u *, struct obstack *));
5199 + static char *get_bp __ARGS((gdb_T *, int, char_u *, struct obstack *));
5200 + static void process_record __ARGS((gdb_T *, struct obstack *));
5201 + static void set_bpfield __ARGS((gdb_T *, char_u *));
5202 + static char *get_display __ARGS((gdb_T *, int, char_u *, struct obstack *));
5203 + static char *undisplay __ARGS((gdb_T *, int, char_u *, struct obstack *));
5205 + /* Variables window management */
5206 + static void var_delete __ARGS((gdb_T *));
5208 + /* The function ordering in this array is important as some of
5209 + * these functions must be invoked in the right order */
5210 + static oobfunc_T oobfunc[] = {
5211 + {gdb_get_pc},
5212 + {gdb_get_frame},
5213 + {gdb_get_sfile},
5214 + {gdb_get_sourcedir},
5215 + {get_lastbp}, /* after gdb_get_frame */
5216 + {gdb_get_asmfunc}, /* after get_lastbp */
5217 + {gdb_get_asmfunc_hack}, /* after gdb_get_asmfunc */
5218 + {gdb_get_asm}, /* after gdb_get_asmfunc */
5219 + {get_bp}, /* after gdb_get_asm and get_lastbp */
5220 + {get_display},
5221 + {undisplay},
5222 + {NULL}
5223 + };
5225 + /* Initialize the gdb_T structure lvl2 component that lvl2 is responsible for */
5226 + static void
5227 + clear_gdb_T(this)
5228 + gdb_T *this;
5230 + gdbdisp_T *item, *next;
5231 + int i;
5233 + if (this != NULL)
5235 + for (item = this->lvl2.varlist.list; item != NULL; item = next)
5237 + next = item->next;
5238 + xfree(item);
5240 + this->lvl2.varlist.list = NULL;
5242 + for (i = 0; i < BI_FIELDS; i++)
5243 + FREE(this->lvl2.info[i]);
5245 + this->lvl2.doing_value = FALSE;
5246 + FREE(this->lvl2.dentry.num);
5247 + FREE(this->lvl2.dentry.expression);
5248 + FREE(this->lvl2.dentry.value);
5249 + FREE(this->lvl2.dispinfostr);
5250 + FREE(this->lvl2.dispinfo);
5254 + /* Initialize lvl2 function pointers */
5255 + void
5256 + gdb_lvl2_init(this)
5257 + gdb_T *this;
5259 + this->mode = GDB_MODE_LVL2;
5260 + this->oobfunc = oobfunc;
5261 + this->std_oobfunc = oobfunc;
5262 + this->parse_output = gdb_parse_output_cli;
5263 + this->gdb_docmd = gdb_docmd_cli;
5264 + this->var_delete = var_delete;
5265 + this->clear_gdb_T = clear_gdb_T;
5268 + /*
5269 + * When a breakpoint is being set and asm option is on, get the
5270 + * instruction address of the last breakpoint, the one being set.
5271 + * This address is used in get_asm() to disassemble the function
5272 + * containing this address.
5273 + */
5274 + static char *
5275 + get_lastbp(this, state, line, obs)
5276 + gdb_T *this;
5277 + int state;
5278 + char_u *line;
5279 + struct obstack *obs;
5281 + int found = FALSE;
5282 + bpinfo_T *p;
5283 + int bp_num;
5284 + int i;
5286 + if (obs) {} /* keep compiler happy */
5288 + switch (state)
5290 + case OOB_CMD:
5291 + /* GDB sends sometimes ANO_BP_INVALID when stepping, even
5292 + * though no breakpoints have been changed.
5293 + * Avoid checking for last bp in this case, because this
5294 + * may cause hiliting a bp in a new buffer when what is
5295 + * expected is a new frame */
5296 + if (this->bp_state & BPS_FR_INVALID)
5297 + return NULL;
5299 + /* A breakpoint is being set in assembly */
5300 + if (p_asm != 0 && (this->bp_state & BPS_INVALID)
5301 + && (this->bp_state & BPS_BP_SET))
5303 + this->bp_state &= ~BPS_BP_SET;
5305 + /* fetch GDB bp table info */
5306 + return "server info breakpoint\n";
5308 + break;
5310 + case OOB_COLLECT:
5311 + /* initialize fields at start of bp record */
5312 + if (this->bp_state & BPS_START)
5314 + this->bp_state &= ~BPS_START;
5316 + for (i = 0; i < BI_FIELDS; i++)
5317 + FREE(this->lvl2.info[i]);
5320 + /* get info[] field from annotation content */
5321 + set_bpfield(this, line);
5322 + break;
5324 + case OOB_COMPLETE:
5325 + /* the last bp in the table */
5326 + if (this->lvl2.info[BI_NUM] != NULL
5327 + && (bp_num = atoi((char *)this->lvl2.info[BI_NUM])) > 0)
5329 + /* look it up in bpinfo list */
5330 + for (p = this->bpinfo; p != NULL; p = p->next)
5332 + if (bp_num == p->id)
5334 + found = TRUE;
5335 + break;
5339 + /* not found: set asm_add so that get_asm will
5340 + * do the disassembling */
5341 + if (! found)
5343 + xfree(this->asm_add);
5344 + this->asm_add =
5345 + gdb_regexec(this->lvl2.info[BI_ADDRESS], PAT_ADD, 1, NULL);
5349 + for (i = 0; i < BI_FIELDS; i++)
5350 + FREE(this->lvl2.info[i]);
5351 + break;
5353 + return NULL;
5356 + /*
5357 + * Get the breakpoints info record table.
5358 + */
5359 + static char *
5360 + get_bp(this, state, line, obs)
5361 + gdb_T *this;
5362 + int state;
5363 + char_u *line;
5364 + struct obstack *obs;
5366 + bpinfo_T *p;
5367 + int i;
5369 + switch (state)
5371 + case OOB_CMD:
5372 + /* When an ANO_BP_INVALID annotation has been received,
5373 + * or when we are stepping (more accurately: got a new frame):
5374 + * fetch bp table */
5375 + if (this->bp_state & BPS_INVALID || this->bp_state & BPS_FR_INVALID)
5377 + this->bufIsChanged = FALSE;
5379 + /* handle case where an error occured last time */
5380 + FREE(this->record);
5381 + gdb_free_bplist(&(this->tmplist));
5383 + return "server info breakpoint\n";
5386 + this->bp_state &= ~BPS_INVALID;
5387 + this->bp_state &= ~BPS_FR_INVALID;
5388 + this->bp_state &= ~BPS_BP_HIT;
5389 + break;
5391 + case OOB_COLLECT:
5392 + if (this->bp_state & BPS_START)
5394 + this->bp_state &= ~BPS_START;
5396 + /* process last record */
5397 + process_record(this, obs);
5398 + for (i = 0; i < BI_FIELDS; i++)
5399 + FREE(this->lvl2.info[i]);
5401 + /* allocate a new record or reuse an existing one
5402 + * and initialize its fields */
5403 + if (this->record == NULL)
5404 + this->record = (bpinfo_T *)xcalloc(sizeof(bpinfo_T));
5406 + this->record->id = -1;
5407 + this->record->enabled = TRUE;
5408 + # ifdef BP_INVALID_ANO_MISSING
5409 + this->record->disposition = TRUE;
5410 + # endif
5411 + this->record->cont = FALSE;
5412 + # ifdef FEAT_GDB
5413 + this->record->buf = NULL;
5414 + # else
5415 + this->record->buf = -1;
5416 + this->record->typenr_en = -1;
5417 + this->record->typenr_dis = -1;
5418 + # endif
5419 + this->record->lnum = 0;
5420 + this->record->next = NULL;
5423 + /* get info[] field from annotation content */
5424 + set_bpfield(this, line);
5425 + break;
5427 + case OOB_COMPLETE:
5428 + /* process last record */
5429 + process_record(this, obs);
5430 + FREE(this->record);
5431 + for (i = 0; i < BI_FIELDS; i++)
5432 + FREE(this->lvl2.info[i]);
5434 + /* All records left in the old table are breakpoints that have
5435 + * been deleted: delete the corresponding highliting sign */
5436 + for (p = this->bpinfo; p != NULL; p = p->next)
5437 + gdb_unlite(BP_SIGN_ID(p->id));
5439 + this->bp_state &= ~BPS_INVALID;
5440 + this->bp_state &= ~BPS_FR_INVALID;
5441 + this->bp_state &= ~BPS_BP_HIT;
5443 + /* replace with new table */
5444 + gdb_free_bplist(&(this->bpinfo));
5445 + this->bpinfo = this->tmplist;
5446 + this->tmplist = NULL;
5447 + break;
5449 + return NULL;
5452 + /* Process the current info record */
5453 + static void
5454 + process_record(this, obs)
5455 + gdb_T *this;
5456 + struct obstack *obs;
5458 + bpinfo_T *record = this->record;
5459 + char_u *bp_add = NULL;
5460 + char_u *bp_at = NULL;
5461 + char_u *bp_line = NULL;
5462 + char_u *bp_source = NULL;
5463 + char_u *ptr;
5465 + if (record == NULL)
5466 + return;
5468 + /* breakpoint number */
5469 + if (this->lvl2.info[BI_NUM] != NULL)
5470 + record->id = atoi((char *)this->lvl2.info[BI_NUM]);
5472 + /* enabled state */
5473 + if (this->lvl2.info[BI_ENABLE] != NULL && *(this->lvl2.info[BI_ENABLE]) == 'n')
5474 + record->enabled = FALSE;
5476 + # ifdef BP_INVALID_ANO_MISSING
5477 + /* disposition */
5478 + if (this->lvl2.info[BI_DISPO] != NULL
5479 + && STRSTR(this->lvl2.info[BI_DISPO], "keep") == NULL)
5480 + record->disposition = FALSE;
5481 + # endif
5483 + /* parse 'commands' for 'continue' as last statement */
5484 + if (this->lvl2.info[BI_CMMDS] != NULL)
5486 + /* get last line */
5487 + if ((ptr = (char_u *)strrchr(
5488 + (char *)this->lvl2.info[BI_CMMDS], (int)'\n')) == NULL)
5489 + ptr = this->lvl2.info[BI_CMMDS];
5490 + else
5491 + ptr++;
5493 + if (gdb_regexec(ptr, PAT_BP_CONT, 1, obs) != NULL
5494 + || gdb_regexec(ptr, PAT_BP_CONT, 2, obs) != NULL)
5496 + record->cont = TRUE; /* continue */
5500 + /* sanity check and discard watchpoints and others */
5501 + if (record->id <= 0 || this->lvl2.info[BI_TYPE] == NULL
5502 + || STRSTR(this->lvl2.info[BI_TYPE], "breakpoint") == NULL
5503 + || this->lvl2.info[BI_ADDRESS] == NULL
5504 + || this->lvl2.info[BI_WHAT] == NULL)
5505 + return;
5507 + bp_add = gdb_regexec(this->lvl2.info[BI_ADDRESS], PAT_ADD, 1, obs);
5508 + bp_line = gdb_regexec(this->lvl2.info[BI_WHAT], PAT_BP_SOURCE, 2, obs);
5509 + bp_source = gdb_regexec(this->lvl2.info[BI_WHAT], PAT_BP_SOURCE, 1, obs);
5510 + if ((bp_at = gdb_regexec(this->lvl2.info[BI_WHAT], PAT_BP_ASM, 1, obs)) == NULL)
5511 + bp_at = gdb_regexec(this->lvl2.info[BI_WHAT], PAT_BP_ASM, 2, obs);
5513 + gdb_process_record(this, bp_add, bp_at, bp_line, bp_source, obs);
5516 + /* Set the annotated indexed field with its possibly partial content */
5517 + static void
5518 + set_bpfield(this, content)
5519 + gdb_T *this;
5520 + char_u *content;
5522 + char_u *res = NULL;
5523 + char_u **pfield;
5525 + /*
5526 + * Set info[] with each breakpoint info field annotation
5527 + */
5528 + if (IS_RECORD(this->bp_state))
5530 + pfield = &(this->lvl2.info[RECORD_INDEX(this->bp_state)]);
5532 + if (*pfield == NULL) /* a new field */
5533 + *pfield = (char_u *)clewn_strsave((char *)content);
5534 + else if (this->annoted) /* concatenate */
5536 + gdb_cat(&res, *pfield);
5537 + gdb_cat(&res, content);
5538 + xfree(*pfield);
5539 + *pfield = res;
5541 + else /* a new line in this field */
5543 + gdb_cat(&res, *pfield);
5544 + gdb_cat(&res, (char_u *)"\n");
5545 + gdb_cat(&res, content);
5546 + xfree(*pfield);
5547 + *pfield = res;
5552 + /*
5553 + * Remove highlighting for all values that are unchanged and get
5554 + * from GDB the current "automatic display list"
5555 + */
5556 + static char *
5557 + get_display(this, state, line, obs)
5558 + gdb_T *this;
5559 + int state;
5560 + char_u *line;
5561 + struct obstack *obs;
5563 + char_u *res = NULL;
5564 + gdbdisp_T *item;
5565 + char_u *oldline;
5566 + char_u *ptr;
5567 + # ifdef FEAT_GDB
5568 + buf_T *oldbuf = curbuf;
5569 + char_u *ptrn;
5570 + win_T *win;
5571 + pos_T pos;
5572 + # endif
5574 + switch(state)
5576 + case OOB_CMD:
5577 + # ifndef FEAT_GDB
5578 + /* tell Vim to not update screen */
5579 + cnb_startAtomic(this->var_buf);
5580 + # endif
5582 + if (
5583 + # ifdef FEAT_GDB
5584 + this->var_buf != NULL && this->lvl2.varlist.state == DSP_STOPPED)
5585 + # else
5586 + this->var_buf > 0 && this->lvl2.varlist.state == DSP_STOPPED)
5587 + # endif
5589 + /* remove highlighting for all values that are unchanged */
5590 + for (item = this->lvl2.varlist.list; item != NULL; item = item->next)
5592 + # ifdef FEAT_GDB
5593 + if (! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
5594 + && ! (item->state & DISP_CHANGED)
5595 + && (item->state & DISP_HILITED))
5597 + pos.lnum = 1;
5598 + pos.col = 0;
5600 + /* search for display item in variables window */
5601 + obstack_strcat(obs, "^\\s*");
5602 + obstack_strcat(obs, gdb_itoa(item->num));
5603 + obstack_strcat0(obs, ":");
5604 + ptrn = (char_u *)obstack_finish(obs);
5606 + if (searchit(NULL, this->var_buf, &pos,
5607 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
5609 + oldline = ml_get_buf(this->var_buf, pos.lnum, FALSE);
5610 + oldline = obstack_strsave(obs, oldline);
5612 + /* this assumes that "={*}" is not valid in
5613 + * any expression or value for all GDB supported
5614 + * languages */
5615 + if ((ptr = STRSTR(oldline, " ={*} ")) != NULL)
5617 + *(ptr + 3) = '=';
5619 + /* replace line */
5620 + curbuf = this->var_buf;
5621 + ml_replace(pos.lnum, oldline, TRUE);
5622 + changed_lines(pos.lnum, 0, pos.lnum + 1, 0);
5623 + curbuf = oldbuf;
5625 + if ((win = gdb_btowin(this->var_buf)) != NULL)
5626 + redraw_win_later(win, NOT_VALID);
5630 + item->state &= ~DISP_HILITED;
5632 + # else
5633 + if (! (item->state & DISP_CHANGED)
5634 + && (item->state & DISP_HILITED))
5636 + int lnum;
5638 + /* search for display item in variables window */
5639 + if ((oldline = cnb_search_obj(gdb_itoa(item->num), &lnum)) != NULL)
5641 + line = obstack_strsave(obs, oldline);
5643 + /* this assumes that "={*}" is not valid in
5644 + * any expression or value for all GDB supported
5645 + * languages */
5646 + if ((ptr = STRSTR(line, " ={*} ")) != NULL)
5648 + *(ptr + 3) = '=';
5650 + /* replace line */
5651 + cnb_replace(this->var_buf, line, lnum, obs);
5654 + item->state &= ~DISP_HILITED;
5656 + # endif
5658 + item->state &= ~DISP_CHANGED;
5661 + FREE(this->lvl2.dispinfostr);
5662 + xfree(this->lvl2.dispinfo);
5663 + this->lvl2.dispinfo = (char_u *)clewn_strsave(" ");
5664 + return "server info display\n";
5666 + break;
5668 + case OOB_COLLECT:
5669 + if (this->annoted) /* concatenate */
5671 + gdb_cat(&res, this->lvl2.dispinfostr);
5672 + gdb_cat(&res, line);
5673 + xfree(this->lvl2.dispinfostr);
5674 + this->lvl2.dispinfostr = res;
5676 + else /* a new line */
5678 + /* add item number to list */
5679 + if ((res = gdb_regexec(this->lvl2.dispinfostr, PAT_DISPINFO, 1, obs)) != NULL)
5681 + gdb_cat(&(this->lvl2.dispinfo), res);
5682 + gdb_cat(&(this->lvl2.dispinfo), (char_u *)" ");
5685 + xfree(this->lvl2.dispinfostr);
5686 + this->lvl2.dispinfostr = (char_u *)clewn_strsave((char *)line);
5688 + break;
5690 + case OOB_COMPLETE:
5691 + /* add last item number to list */
5692 + if ((res = gdb_regexec(this->lvl2.dispinfostr, PAT_DISPINFO, 1, obs)) != NULL)
5694 + gdb_cat(&(this->lvl2.dispinfo), res);
5695 + gdb_cat(&(this->lvl2.dispinfo), (char_u *)" ");
5697 + FREE(this->lvl2.dispinfostr);
5698 + break;
5700 + return NULL;
5703 + /*
5704 + * Synchronise the gdb variables window list and our varlist with
5705 + * GDB "automatic display list".
5706 + * It should be sufficient that all items in varlist are included
5707 + * both in the gdb variables window list and in GDB
5708 + * "automatic display list".
5709 + */
5710 + static char *
5711 + undisplay(this, state, line, obs)
5712 + gdb_T *this;
5713 + int state;
5714 + char_u *line;
5715 + struct obstack *obs;
5716 + # ifdef FEAT_GDB
5718 + char_u *sequence = NULL; /* sequence of items to undisplay */
5719 + win_T *oldwin = curwin;
5720 + buf_T *oldbuf = curbuf;
5721 + char_u *num;
5722 + char_u *ptrn;
5723 + gdbdisp_T **pt;
5724 + gdbdisp_T *next;
5725 + char_u *numstr;
5726 + pos_T pos;
5727 + win_T *win;
5729 + switch(state)
5731 + case OOB_CMD:
5732 + if (this->lvl2.varlist.state == DSP_STOPPED)
5734 + for (pt = &(this->lvl2.varlist.list); *pt != NULL; )
5736 + numstr = gdb_itoa((*pt)->num);
5738 + /* not in * GDB "automatic display list" */
5739 + obstack_strcat(obs, " ");
5740 + obstack_strcat(obs, numstr);
5741 + obstack_strcat0(obs, " ");
5742 + num = (char_u *)obstack_finish(obs);
5744 + if (this->lvl2.dispinfo != NULL
5745 + && this->var_buf != NULL
5746 + && STRSTR(this->lvl2.dispinfo, num) == NULL)
5748 + pos.lnum = 1;
5749 + pos.col = 0;
5751 + /* remove line from window if exists */
5752 + obstack_strcat(obs, "^\\s*");
5753 + obstack_strcat(obs, numstr);
5754 + obstack_strcat0(obs, ":");
5755 + ptrn = (char_u *)obstack_finish(obs);
5757 + if (! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
5758 + && searchit(NULL, this->var_buf, &pos,
5759 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
5761 + curbuf = this->var_buf;
5762 + ml_delete(pos.lnum, FALSE);
5763 + deleted_lines(pos.lnum, 1);
5765 + if ((win = gdb_btowin(this->var_buf)) != NULL)
5767 + curwin = win;
5768 + check_cursor();
5769 + update_topline();
5770 + curwin = oldwin;
5772 + win->w_redr_status = TRUE;
5774 + redraw_win_later(win, NOT_VALID);
5776 + curbuf = oldbuf;
5779 + /* remove from varlist */
5780 + next = (*pt)->next;
5781 + xfree(*pt);
5782 + *pt = next;
5784 + continue;
5787 + /* not in gdb variables window */
5788 + obstack_strcat(obs, "^\\s*");
5789 + obstack_strcat(obs, numstr);
5790 + obstack_strcat0(obs, ":");
5791 + ptrn = (char_u *)obstack_finish(obs);
5793 + if (this->var_buf == NULL
5794 + || (this->var_buf->b_ml.ml_flags & ML_EMPTY)
5795 + || (searchit(NULL, this->var_buf, &pos,
5796 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) == FAIL))
5798 + /* add to sequence */
5799 + obstack_strcat(obs, numstr);
5800 + obstack_strcat0(obs, " ");
5801 + sequence = (char_u *)obstack_finish(obs);
5803 + /* remove from varlist */
5804 + next = (*pt)->next;
5805 + xfree(*pt);
5806 + *pt = next;
5808 + continue;
5811 + pt = &((*pt)->next);
5814 + this->lvl2.varlist.state = DSP_INIT;
5815 + FREE(this->lvl2.dispinfo);
5817 + if (sequence != NULL)
5819 + obstack_strcat(obs, "server undisplay ");
5820 + obstack_strcat(obs, sequence);
5821 + obstack_strcat0(obs, "\n");
5822 + return (char *)obstack_finish(obs);
5825 + break;
5827 + case OOB_COMPLETE:
5828 + line = NULL; /* keep compiler happy */
5829 + break;
5831 + return NULL;
5833 + # else
5835 + char_u *sequence = NULL; /* sequence of items to undisplay */
5836 + char_u *num;
5837 + gdbdisp_T **pt;
5838 + gdbdisp_T *next;
5839 + char_u *numstr;
5840 + int lnum;
5842 + switch(state)
5844 + case OOB_CMD:
5845 + if (this->lvl2.varlist.state == DSP_STOPPED)
5847 + for (pt = &(this->lvl2.varlist.list); *pt != NULL; )
5849 + numstr = gdb_itoa((*pt)->num);
5851 + /* not in * GDB "automatic display list" */
5852 + obstack_strcat(obs, " ");
5853 + obstack_strcat(obs, numstr);
5854 + obstack_strcat0(obs, " ");
5855 + num = (char_u *)obstack_finish(obs);
5857 + if (this->lvl2.dispinfo != NULL
5858 + && this->var_buf > 0
5859 + && STRSTR(this->lvl2.dispinfo, num) == NULL)
5861 + /* replace line in window if exists with an empty line */
5862 + if (cnb_search_obj(numstr, &lnum) != NULL)
5863 + cnb_replace(this->var_buf, "", lnum, obs);
5865 + /* remove from varlist */
5866 + next = (*pt)->next;
5867 + xfree(*pt);
5868 + *pt = next;
5870 + continue;
5873 + /* not in gdb variables window */
5874 + if (this->var_buf <= 0 || cnb_search_obj(numstr, &lnum) == NULL)
5876 + /* add to sequence */
5877 + obstack_strcat(obs, numstr);
5878 + obstack_strcat0(obs, " ");
5879 + sequence = (char_u *)obstack_finish(obs);
5881 + /* remove from varlist */
5882 + next = (*pt)->next;
5883 + xfree(*pt);
5884 + *pt = next;
5886 + continue;
5889 + pt = &((*pt)->next);
5892 + this->lvl2.varlist.state = DSP_INIT;
5893 + FREE(this->lvl2.dispinfo);
5895 + if (sequence != NULL)
5897 + obstack_strcat(obs, "server undisplay ");
5898 + obstack_strcat(obs, sequence);
5899 + obstack_strcat0(obs, "\n");
5900 + return (char_u *)obstack_finish(obs);
5903 + /* tell Vim to update screen */
5904 + cnb_endAtomic(this->var_buf);
5905 + break;
5907 + case OOB_COMPLETE:
5908 + /* tell Vim to update screen */
5909 + cnb_endAtomic(this->var_buf);
5910 + line = NULL; /* keep compiler happy */
5911 + break;
5913 + return NULL;
5915 + # endif
5917 + /*
5918 + * Handle the content of a display annotation.
5919 + * Fill up each field.
5920 + * When entry complete, process it:
5921 + * . if it's the result of a GDB "display" command with an argument:
5922 + * add to variables window and varlist
5923 + * . if it is the output produced by GDB when the program stops or
5924 + * an equivalent GDB "display" command without argument: hilite
5925 + * changed values in variables window
5926 + */
5927 + void
5928 + gdb_process_display(this, line, obs)
5929 + gdb_T *this;
5930 + char_u *line; /* display annotation content */
5931 + struct obstack *obs;
5933 + char_u *res = NULL;
5934 + int note = this->note;
5935 + char_u *displine; /* the new display item line */
5936 + gdbdisp_T *item;
5937 + char_u *last, *end, *start;
5938 + char_u *ptr;
5939 + int num;
5940 + # ifdef FEAT_GDB
5941 + win_T *oldwin = curwin;
5942 + buf_T *oldbuf = curbuf;
5943 + char_u *ptrn;
5944 + linenr_T lnum;
5945 + win_T *win;
5946 + pos_T pos;
5947 + # endif
5949 + # ifdef FEAT_GDB
5950 + if (this->var_buf == NULL)
5951 + # else
5952 + if (this->var_buf <= 0)
5953 + # endif
5954 + return;
5956 + /* GDB bug: outputs ANO_DISP_EXP instead of ANO_DISP_VALUE
5957 + * use doing_value as a hack to know when we are parsing the value */
5958 + if (this->lvl2.doing_value && note == ANO_DISP_EXP)
5959 + note = ANO_DISP_VALUE;
5961 + /* nested structure or array */
5962 + if (this->lvl2.doing_value
5963 + && ((note >= ANO_FIELD_BEG && note <= ANO_FIELD_END)
5964 + || (note >= ANO_ARRAY_BEG && note <= ANO_ARRAY_END)))
5965 + note = ANO_DISP_VALUE;
5967 + switch (note)
5969 + case ANO_DISP_BEG:
5970 + # ifndef FEAT_GDB
5971 + /* tell Vim to not update screen */
5972 + cnb_startAtomic(this->var_buf);
5973 + # endif
5975 + this->lvl2.doing_value = FALSE;
5977 + /* display number */
5978 + if (this->lvl2.dentry.num == NULL)
5979 + this->lvl2.dentry.num = (char_u *)clewn_strsave((char *)line);
5980 + else
5982 + gdb_cat(&res, this->lvl2.dentry.num);
5983 + gdb_cat(&res, line);
5984 + xfree(this->lvl2.dentry.num);
5985 + this->lvl2.dentry.num = res;
5987 + break;
5989 + case ANO_DISP_FMT:
5990 + case ANO_DISP_EXP:
5991 + /* display format and expression */
5992 + if (this->lvl2.dentry.expression == NULL)
5993 + this->lvl2.dentry.expression = (char_u *)clewn_strsave((char *)line);
5994 + else
5996 + gdb_cat(&res, this->lvl2.dentry.expression);
5997 + gdb_cat(&res, line);
5998 + xfree(this->lvl2.dentry.expression);
5999 + this->lvl2.dentry.expression = res;
6001 + break;
6003 + case ANO_DISP_EXPEND:
6004 + this->lvl2.doing_value = TRUE;
6005 + break;
6007 + case ANO_DISP_VALUE:
6008 + /* display value */
6009 + if (this->lvl2.dentry.value == NULL)
6010 + this->lvl2.dentry.value = (char_u *)clewn_strsave((char *)line);
6011 + else
6013 + gdb_cat(&res, this->lvl2.dentry.value);
6014 + gdb_cat(&res, line);
6015 + xfree(this->lvl2.dentry.value);
6016 + this->lvl2.dentry.value = res;
6018 + break;
6020 + /* Process the entry now it's complete */
6021 + case ANO_DISP_END:
6022 + this->lvl2.doing_value = FALSE;
6024 + /* sanity checks */
6025 + if (this->lvl2.dentry.num == NULL
6026 + || (num = atoi((char *)this->lvl2.dentry.num)) <= 0
6027 + || this->lvl2.dentry.expression == NULL
6028 + || this->lvl2.dentry.value == NULL)
6030 + FREE(this->lvl2.dentry.num);
6031 + FREE(this->lvl2.dentry.expression);
6032 + FREE(this->lvl2.dentry.value);
6033 + return;
6036 + /* Build the display line including ={*}, the hiliting sign */
6037 + obstack_strcat(obs, this->lvl2.dentry.num);
6038 + obstack_strcat(obs, ":");
6039 + obstack_strcat(obs, this->lvl2.dentry.expression);
6040 + obstack_strcat(obs, " ={*} ");
6041 + obstack_strcat0(obs, this->lvl2.dentry.value);
6042 + displine = (char_u *)obstack_finish(obs);
6044 + /*
6045 + * The result of a GDB "display" command with argument
6046 + */
6047 + if (this->cmd_type == CMD_DISPLAY)
6049 + item = (gdbdisp_T *)xcalloc(sizeof(gdbdisp_T));
6051 + /* add item to varlist */
6052 + item->num = num;
6053 + item->state = DISP_HILITED;
6054 + item->next = this->lvl2.varlist.list;
6055 + this->lvl2.varlist.list = item;
6057 + # ifdef FEAT_GDB
6058 + lnum = BUFLASTL(this->var_buf);
6060 + /* edit variables buffer in available window */
6061 + if (gdb_edit_file(this, this->var_buf, NULL, lnum, obs) != NULL)
6063 + /* add to variables buffer */
6064 + if (ml_append(lnum, displine, 0, 0) == OK)
6066 + /* first line ever: remove empty line after the
6067 + * one just inserted */
6068 + if (lnum == 0)
6069 + ml_delete(this->var_buf->b_ml.ml_line_count, FALSE);
6071 + changed_lines(this->var_buf->b_ml.ml_line_count - 1,
6072 + 0, this->var_buf->b_ml.ml_line_count, 1);
6075 + /* update top line */
6076 + curwin->w_cursor.lnum = this->var_buf->b_ml.ml_line_count;
6077 + update_topline();
6079 + /* status line changed */
6080 + curwin->w_redr_status = TRUE;
6082 + /* move back to previous window if still there */
6083 + if ((win = gdb_btowin(oldbuf)) != NULL)
6084 + win_goto(win);
6086 + # else
6087 + /* add to variables buffer */
6088 + cnb_append(this->var_buf, displine, obs);
6089 + # endif
6092 + /*
6093 + * Highlight existing changed values in variables window
6094 + */
6095 + else
6097 + # ifdef FEAT_GDB
6098 + pos.lnum = 1;
6099 + pos.col = 0;
6101 + /* search for display item in variables window */
6102 + obstack_strcat(obs, "^\\s*");
6103 + obstack_strcat(obs, this->lvl2.dentry.num);
6104 + obstack_strcat0(obs, ":");
6105 + ptrn = (char_u *)obstack_finish(obs);
6107 + if ( ! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
6108 + && searchit(NULL, this->var_buf, &pos,
6109 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
6111 + lnum = pos.lnum;
6113 + obstack_strcat(obs, "} ");
6114 + obstack_strcat0(obs, this->lvl2.dentry.value);
6115 + res = (char_u *)obstack_finish(obs);
6117 + last = NULL;
6118 + start = ml_get_buf(this->var_buf, lnum, FALSE);
6119 + end = start + STRLEN(start);
6121 + /* get last occurence of "} " + value in this line */
6122 + for (ptr = start; ptr != NULL; )
6123 + if ((ptr=STRSTR(ptr, res)) != NULL)
6125 + last = ptr;
6126 + ptr++;
6129 + /* a changed value (res not found at line end) */
6130 + if (last == NULL || end != last + STRLEN(res))
6132 + /* replace line */
6133 + curbuf = this->var_buf;
6134 + ml_replace(lnum, displine, TRUE);
6135 + changed_lines(lnum, 0, lnum + 1, 0);
6137 + if ((win = gdb_btowin(this->var_buf)) != NULL)
6139 + win->w_cursor.lnum = lnum;
6141 + curwin = win;
6142 + check_cursor();
6143 + update_topline();
6144 + curwin = oldwin;
6146 + win->w_redr_status = TRUE;
6148 + redraw_win_later(win, NOT_VALID);
6150 + curbuf = oldbuf;
6152 + /* update item state */
6153 + for (item = this->lvl2.varlist.list; item != NULL;
6154 + item = item->next)
6155 + if (item->num == num)
6157 + item->state |= DISP_HILITED | DISP_CHANGED;
6158 + break;
6162 + # else
6163 + int line_nb;
6165 + /* search for display item in variables window */
6166 + if ((start = cnb_search_obj(this->lvl2.dentry.num, &line_nb)) != NULL)
6168 + obstack_strcat(obs, "} ");
6169 + obstack_strcat0(obs, this->lvl2.dentry.value);
6170 + res = (char_u *)obstack_finish(obs);
6172 + last = NULL;
6173 + end = start + STRLEN(start);
6175 + /* get last occurence of "} " + value in this line */
6176 + for (ptr = start; ptr != NULL; )
6177 + if ((ptr=STRSTR(ptr, res)) != NULL)
6179 + last = ptr;
6180 + ptr++;
6183 + /* a changed value (res not found at line end) */
6184 + if (last == NULL || end != last + STRLEN(res))
6186 + /* replace line */
6187 + cnb_replace(this->var_buf, displine, line_nb, obs);
6189 + /* update item state */
6190 + for (item = this->lvl2.varlist.list; item != NULL;
6191 + item = item->next)
6192 + if (item->num == num)
6194 + item->state |= DISP_HILITED | DISP_CHANGED;
6195 + break;
6199 + # endif
6202 + FREE(this->lvl2.dentry.num);
6203 + FREE(this->lvl2.dentry.expression);
6204 + FREE(this->lvl2.dentry.value);
6206 + # ifndef FEAT_GDB
6207 + /* tell Vim to update screen */
6208 + cnb_endAtomic(this->var_buf);
6209 + # endif
6210 + break;
6212 + default:
6213 + break;
6217 + /* Undisplay all variables */
6218 + static void
6219 + var_delete(this)
6220 + gdb_T *this;
6222 + struct obstack obs; /* use an obstack for temporary allocated memory */
6223 + char_u *res;
6225 + /* undisplay all */
6226 + this->lvl2.varlist.state = DSP_STOPPED;
6228 + (void)obstack_init(&obs);
6230 + if ((res = (char_u *)undisplay(this, OOB_CMD, (char_u *)"", &obs)) != NULL)
6231 + gdb_send_cmd(this, res);
6233 + obstack_free(&obs, NULL);
6235 + # endif /* GDB_LVL2_SUPPORT */
6236 + #endif /* defined(FEAT_GDB) || defined(HAVE_CLEWN) */
6237 diff -c --new-file old/clewn/gdb_lvl3.c src/clewn/gdb_lvl3.c
6238 *** old/clewn/gdb_lvl3.c 1970-01-01 01:00:00.000000000 +0100
6239 --- src/clewn/gdb_lvl3.c 2008-10-13 16:38:07.000000000 +0200
6240 ***************
6241 *** 0 ****
6242 --- 1,4116 ----
6243 + /* vi:set ts=8 sts=4 sw=4:
6245 + * Copyright (C) 2004 Xavier de Gaye.
6247 + * This program is free software; you can redistribute it and/or modify
6248 + * it under the terms of the GNU General Public License as published by
6249 + * the Free Software Foundation; either version 2, or (at your option)
6250 + * any later version.
6252 + * This program is distributed in the hope that it will be useful,
6253 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6254 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6255 + * GNU General Public License for more details.
6257 + * You should have received a copy of the GNU General Public License
6258 + * along with this program (see the file COPYING); if not, write to the
6259 + * Free Software Foundation, Inc.,
6260 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
6262 + * $Id: gdb_lvl3.c 222 2008-10-13 14:38:07Z xavier $
6263 + */
6265 + # ifdef HAVE_CLEWN
6266 + # include <config.h>
6267 + # include "obstack.h"
6268 + # include "clewn.h"
6269 + static int got_int; /* not used with Clewn */
6270 + # else
6271 + # include "vim.h"
6272 + # include "clewn/obstack.h"
6273 + # endif
6275 + #if defined(FEAT_GDB) || defined(HAVE_CLEWN)
6277 + # include "gdb.h"
6278 + # include "misc.h"
6280 + # if defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT)
6282 + static char gdb_buf[MAX_BUFFSIZE]; /* general purpose buffer */
6284 + typedef struct
6286 + int id; /* annoted identifier */
6287 + char_u *str; /* GDB annotation */
6288 + } annotation_T;
6290 + static annotation_T annotations[] = {
6291 + {ANO_PREPROMPT, (char_u *)"pre-prompt"},
6292 + {ANO_PROMPT, (char_u *)"prompt"},
6293 + {ANO_POSTPROMPT, (char_u *)"post-prompt"},
6294 + {ANO_PRECMDS, (char_u *)"pre-commands"},
6295 + {ANO_CMDS, (char_u *)"commands"},
6296 + {ANO_PREOVERLOAD, (char_u *)"pre-overload-choice"},
6297 + {ANO_OVERLOAD, (char_u *)"overload-choice"},
6298 + {ANO_PREQUERY, (char_u *)"pre-query"},
6299 + {ANO_QUERY, (char_u *)"query"},
6300 + {ANO_PREPMT_FORMORE, (char_u *)"pre-prompt-for-continue"},
6301 + {ANO_PMT_FORMORE, (char_u *)"prompt-for-continue"},
6302 + {ANO_POSTPMT_FORMORE, (char_u *)"post-prompt-for-continue"},
6303 + {ANO_QUIT, (char_u *)"quit"},
6304 + {ANO_ERROR_BEG, (char_u *)"error-begin"},
6305 + {ANO_FRAME_INVALID, (char_u *)"frames-invalid"},
6306 + {ANO_BP_INVALID, (char_u *)"breakpoints-invalid"},
6307 + {ANO_STARTING, (char_u *)"starting"},
6308 + {ANO_STOPPED, (char_u *)"stopped"},
6309 + {ANO_EXITED, (char_u *)"exited"},
6310 + {ANO_SIGNALLED, (char_u *)"signalled"},
6311 + {ANO_BREAKPOINT, (char_u *)"breakpoint"},
6312 + # ifdef GDB_LVL2_SUPPORT
6313 + {ANO_SOURCE, (char_u *)"source"},
6314 + {ANO_FRAME_BEGIN, (char_u *)"frame-begin"},
6315 + {ANO_FRAME_END, (char_u *)"frame-end"},
6316 + {ANO_BP_HEADER, (char_u *)"breakpoints-headers"},
6317 + {ANO_BP_TABLE, (char_u *)"breakpoints-table"},
6318 + {ANO_BP_RECORD, (char_u *)"record"},
6319 + {ANO_BP_FIELD0, (char_u *)"field 0"},
6320 + {ANO_BP_FIELD1, (char_u *)"field 1"},
6321 + {ANO_BP_FIELD2, (char_u *)"field 2"},
6322 + {ANO_BP_FIELD3, (char_u *)"field 3"},
6323 + {ANO_BP_FIELD4, (char_u *)"field 4"},
6324 + {ANO_BP_FIELD5, (char_u *)"field 5"},
6325 + {ANO_BP_FIELD6, (char_u *)"field 6"},
6326 + {ANO_BP_FIELD7, (char_u *)"field 7"},
6327 + {ANO_BP_FIELD8, (char_u *)"field 8"},
6328 + {ANO_BP_FIELD9, (char_u *)"field 9"},
6329 + {ANO_BP_END, (char_u *)"breakpoints-table-end"},
6330 + {ANO_DISP_BEG, (char_u *)"display-begin"},
6331 + {ANO_DISP_NUMEND, (char_u *)"display-number-end"},
6332 + {ANO_DISP_FMT, (char_u *)"display-format"},
6333 + {ANO_DISP_EXP, (char_u *)"display-expression"},
6334 + {ANO_DISP_EXPEND, (char_u *)"display-expression-end"},
6335 + {ANO_DISP_VALUE, (char_u *)"display-value"},
6336 + {ANO_DISP_END, (char_u *)"display-end"},
6337 + {ANO_FIELD_BEG, (char_u *)"field-begin"},
6338 + {ANO_FIELD_NAMEND, (char_u *)"field-name-end"},
6339 + {ANO_FIELD_VALUE, (char_u *)"field-value"},
6340 + {ANO_FIELD_END, (char_u *)"field-end"},
6341 + {ANO_ARRAY_BEG, (char_u *)"array-section-begin"},
6342 + {ANO_ARRAY_ELT, (char_u *)"elt"},
6343 + {ANO_ARRAY_ELTREP, (char_u *)"elt-rep"},
6344 + {ANO_ARRAY_ELTEND, (char_u *)"elt-rep-end"},
6345 + {ANO_ARRAY_END, (char_u *)"array-section-end"},
6346 + # endif
6347 + {0, NULL}
6348 + };
6350 + /* User interface */
6351 + static char_u *process_cmd __ARGS((gdb_T *, char_u *));
6353 + /* Vim low level hook */
6354 + /* Not allowed after ^O in INS REP mode or from the input-line window */
6355 + static char_u *process_annotation __ARGS((gdb_T *, char_u *, struct obstack *));
6356 + static char_u * process_completion __ARGS((cli_cmd_T *, char_u *, struct obstack *));
6357 + static char_u * eol_choices __ARGS((cli_cmd_T *, struct obstack *));
6359 + # ifdef GDB_LVL3_SUPPORT
6360 + /* Gdb process mgmt */
6361 + static void clear_gdb_T __ARGS((gdb_T *));
6363 + /* Out Of Band */
6364 + static char *get_lastbp __ARGS((gdb_T *, int, char_u *, struct obstack *));
6365 + static char *get_bp __ARGS((gdb_T *, int, char_u *, struct obstack *));
6366 + static void process_record __ARGS((gdb_T *, char_u *, struct obstack *));
6367 + static char *varobj_update __ARGS((gdb_T *, int, char_u *, struct obstack *));
6368 + static char *varobj_complete __ARGS((gdb_T *, struct obstack *));
6369 + static void varobj_hilite __ARGS((gdb_T *, varobj_T *, int, struct obstack *));
6370 + static void varobj_replace __ARGS((gdb_T *, varobj_T *, char_u *, struct obstack *));
6371 + static void remove_object __ARGS((gdb_T *, varobj_T *));
6372 + # endif
6374 + /* Utilities */
6375 + static char_u * parse_note __ARGS((gdb_T *, char_u *));
6376 + # ifndef FEAT_GDB
6377 + static int get_note __ARGS((gdb_T *, char_u *));
6378 + # endif
6380 + # ifdef GDB_LVL3_SUPPORT
6381 + /* The function ordering in this array is important as some of
6382 + * these functions must be invoked in the right order */
6383 + static oobfunc_T oobfunc[] = {
6384 + {gdb_get_pc},
6385 + {gdb_get_frame},
6386 + {gdb_get_sourcedir},
6387 + #ifndef FEAT_GDB
6388 + {gdb_source_project},
6389 + {gdb_get_pwd},
6390 + {gdb_get_args},
6391 + #endif
6392 + {gdb_source_cur},
6393 + {gdb_source_list},
6394 + {gdb_get_sfile},
6395 + {gdb_info_frame},
6396 + {gdb_stack_frame}, /* after gdb_info_frame */
6397 + {get_lastbp}, /* after gdb_get_frame */
6398 + {gdb_get_asmfunc}, /* after get_lastbp */
6399 + {gdb_get_asmfunc_hack}, /* after gdb_get_asmfunc */
6400 + {gdb_get_asm}, /* after gdb_get_asmfunc */
6401 + {get_bp}, /* after gdb_get_asm and get_lastbp */
6402 + {varobj_update},
6403 + {NULL}
6404 + };
6405 + # endif
6407 + /** Send a cmd to gdb */
6408 + void
6409 + gdb_docmd_cli(this, cmd)
6410 + gdb_T *this;
6411 + char_u *cmd; /* gdb cmd */
6413 + # ifdef GDB_LVL3_SUPPORT
6414 + char_u *expression = NULL;
6415 + varobj_T *varobj;
6416 + # endif
6417 + char_u *res;
6418 + char_u *ptr;
6419 + char_u *last;
6420 + int len;
6422 + /* make a copy so we can mess with it */
6423 + if (cmd == NULL)
6425 + this->cmd_type = CMD_ANY;
6426 + goto empty_cmd;
6428 + cmd = (char_u *)clewn_strsave((char *)cmd);
6430 + /* remove illegal characters */
6431 + for (ptr = last = cmd; *last != NUL; last++)
6432 + if (*last == NL
6433 + || *last == TAB
6434 + || *last == KEY_INTERUPT
6435 + || !iscntrl((int)(*last)))
6436 + *ptr++ = *last;
6437 + *ptr = NUL;
6439 + /* remove backslash at last position */
6440 + if (ptr != cmd && *(ptr - 1) == '\\')
6441 + *(ptr - 1) = NUL;
6443 + if (this->cli_cmd.state == CS_QUERY || this->note == ANO_QUERY)
6445 + if (*cmd == NUL)
6446 + goto empty_cmd;
6447 + goto send;
6450 + /* now we can forget last cmd */
6451 + this->cmd_type = CMD_ANY;
6453 + /* an interrupt */
6454 + if (STRCHR(cmd, KEY_INTERUPT) != NULL)
6455 + goto send;
6457 + /* a TAB */
6458 + if (STRCHR(cmd, TAB) != NULL)
6460 + gdb_cmd_type(this, cmd); /* get cmd type */
6462 + /* handle completion for all non-gdb commands */
6463 + if (this->cmd_type == CMD_RESTART) {
6464 + gdb_setwinput((gdb_handle_T *)this, (char_u *)"cl_restart ");
6465 + xfree(cmd);
6466 + this->oob.state &= ~OS_CMD;
6467 + return;
6469 + else if (this->cmd_type == CMD_CREATEVAR)
6471 + gdb_setwinput((gdb_handle_T *)this, (char_u *)"createvar ");
6472 + xfree(cmd);
6473 + this->oob.state &= ~OS_CMD;
6474 + return;
6476 + goto send;
6479 + if ((res = gdb_regexec(cmd, PAT_CHG_ANNO, 0, NULL)) != NULL)
6481 + EMSG(_("Sorry, cannot change annotation level"));
6482 + xfree(res);
6483 + goto empty_cmd;
6486 + # ifndef FEAT_GDB /* Clewn follows GDB behavior with empty commands */
6487 + if (*cmd == NUL)
6489 + gdb_send_cmd(this, (char_u *)"\n");
6490 + xfree(cmd);
6491 + return;
6493 + # endif
6495 + /* process the cmd */
6496 + if ((res = process_cmd(this, cmd)) != NULL)
6498 + xfree(cmd);
6499 + cmd = res;
6501 + # ifdef GDB_LVL3_SUPPORT
6502 + /* a |+gdb| createvar command is processed later in oob varobj_update() */
6503 + if (this->mode == GDB_MODE_LVL3 && this->cmd_type == CMD_CREATEVAR)
6505 + # ifdef FEAT_GDB
6506 + if (this->var_buf == NULL)
6507 + # else
6508 + if (this->var_buf <= 0)
6509 + # endif
6511 + EMSG(_("Variables buffer does not exist anymore: unable to create variable"));
6512 + goto empty_cmd;
6515 + if (
6516 + # ifdef FEAT_GDB
6517 + (expression = gdb_regexec(cmd, PAT_CRVAR_FMT, 2, NULL)) != NULL
6518 + # else
6519 + (expression = gdb_regexec(cmd, PAT_CRVAR_FMT, 3, NULL)) != NULL
6520 + # endif
6521 + && *expression != NUL)
6523 + varobj = (varobj_T *)xcalloc(sizeof(varobj_T));
6525 + /* create a new varobj_T element and link it to the list */
6526 + varobj->state = VS_INIT;
6527 + varobj->children = FALSE;
6528 + # ifdef FEAT_GDB
6529 + varobj->format = gdb_regexec(cmd, PAT_CRVAR_FMT, 1, NULL);
6530 + # else
6531 + varobj->format = gdb_regexec(cmd, PAT_CRVAR_FMT, 2, NULL);
6532 + # endif
6533 + varobj->expression = expression;
6534 + varobj->next = this->lvl3.varlist;
6535 + this->lvl3.varlist = varobj;
6537 + goto empty_cmd;
6540 + xfree(expression);
6541 + EMSG(_("Unvalid arguments to \"createvar\" command"));
6542 + goto empty_cmd;
6544 + # endif
6546 + else
6547 + goto empty_cmd;
6549 + /* add a newline to cmd if needed */
6550 + len = STRLEN(cmd);
6551 + if (len == 0 || *(cmd + len - 1) != NL)
6553 + res = NULL;
6554 + gdb_cat(&res, cmd);
6555 + gdb_cat(&res, (char_u *)"\n");
6556 + xfree(cmd);
6557 + cmd = res;
6559 + send:
6560 + gdb_send_cmd(this, cmd);
6561 + xfree(cmd);
6562 + return;
6563 + empty_cmd:
6564 + gdb_send_cmd(this, (char_u *)" \n");
6565 + xfree(cmd);
6566 + return;
6569 + /*
6570 + * Process a gdb cmd according to its type.
6571 + * Return an allocated sanitized cmd or NULL if error.
6572 + */
6573 + static char_u *
6574 + process_cmd(this, cmd)
6575 + gdb_T *this;
6576 + char_u *cmd; /* user's gdb cmd */
6578 + char_u *delete = NULL;
6579 + char_u *range = NULL;
6580 + char_u *res;
6581 + # ifdef FEAT_GDB
6582 + int i;
6583 + buf_T *buf = NULL;
6584 + win_T *oldwin = curwin;
6585 + # endif
6587 + /* make a copy so we can mess with it */
6588 + if (cmd == NULL || *cmd == NUL)
6589 + return NULL;
6590 + cmd = (char_u *)clewn_strsave((char *)cmd);
6592 + gdb_cmd_type(this, cmd); /* get cmd type */
6594 + # ifdef GDB_LVL2_SUPPORT
6595 + /* Replace "createvar" command with GDB "display" command */
6596 + if (this->mode == GDB_MODE_LVL2 && this->cmd_type == CMD_CREATEVAR)
6598 + # ifdef FEAT_GDB
6599 + if ((res = gdb_regexec(cmd, PAT_CREATEVAR, 1, NULL)) != NULL)
6600 + # else
6601 + if ((res = gdb_regexec(cmd, PAT_CREATEVAR, 2, NULL)) != NULL)
6602 + # endif
6604 + /* replace */
6605 + this->cmd_type = CMD_DISPLAY;
6606 + FREE(cmd);
6607 + gdb_cat(&cmd, (char_u *)"display ");
6608 + gdb_cat(&cmd, res);
6609 + xfree(res);
6611 + if (cmd == NULL)
6613 + this->cmd_type = CMD_ANY;
6614 + return NULL;
6618 + # endif
6620 + # ifndef FEAT_GDB
6621 + /* Prevent use of a low height size because of "prompt-for-continue" messages.
6622 + * The annotations lines printed by GDB are part of the lines count that
6623 + * is used by GDB for "prompt-for-continue" messages, however we do not
6624 + * display them. */
6625 + if ((res = gdb_regexec(cmd, PAT_HEIGHT, 2, NULL)) != NULL)
6627 + fprintf(stderr, "Cannot change the screen size\n");
6628 + xfree(cmd);
6629 + xfree(res);
6630 + return NULL;
6632 + # endif
6634 + /* Cannot attach to oneself */
6635 + # ifdef FEAT_GDB
6636 + if ((res = gdb_regexec(cmd, PAT_PID, 1, NULL)) != NULL)
6637 + # else
6638 + if ((res = gdb_regexec(cmd, PAT_PID, 2, NULL)) != NULL)
6639 + # endif
6641 + if (getpid() == atoi((char *)res))
6643 + EMSG(_("I refuse to debug myself!"));
6644 + xfree(cmd);
6645 + xfree(res);
6646 + return NULL;
6648 + xfree(res);
6651 + /* no processing for 'define' type cmds */
6652 + if (this->note == ANO_CMDS || this->note == ANO_OVERLOAD)
6653 + return cmd;
6655 + switch (this->cmd_type)
6657 + # ifdef GDB_LVL2_SUPPORT
6658 + case CMD_DISPLAY:
6659 + /* A "display" command without argument is equivalent to the
6660 + * debuggee being stopped */
6661 + if ((res = gdb_regexec(cmd, PAT_DISPLAY, 0, NULL)) != NULL)
6663 + xfree(res);
6664 + this->cmd_type = CMD_ANY;
6665 + # ifdef FEAT_GDB
6666 + if (this->var_buf != NULL)
6667 + # else
6668 + if (this->var_buf > 0)
6669 + # endif
6670 + this->lvl2.varlist.state = DSP_STOPPED;
6672 + break;
6673 + # endif
6675 + case CMD_SHELL:
6676 + EMSG(_("Sorry, cannot spawn a shell"));
6677 + xfree(cmd);
6678 + return NULL;
6680 + /* unlite frame on 'detach' */
6681 + case CMD_DETACH:
6682 + gdb_fr_unlite(this);
6683 + break;
6685 + /* clear dirty asm buffers */
6686 + case CMD_EXECF:
6687 + # ifdef FEAT_GDB
6688 + for (i = 0; i < this->pool.max; i++)
6690 + if ((curbuf = this->pool.buf[i]) == NULL)
6691 + continue;
6693 + /* clear the buffer */
6694 + gdb_clear_asmbuf(this, curbuf);
6696 + /* asm buffer is displayed */
6697 + if ((curwin = gdb_btowin(curbuf)) != NULL)
6699 + check_cursor();
6700 + buf = curbuf;
6702 + curwin = oldwin;
6704 + curbuf = curwin->w_buffer;
6705 + gdb_redraw(buf); /* redraw only if one asm displayed */
6706 + # else
6707 + /* unlink all asm buffers */
6708 + cnb_unlink_asm();
6709 + # endif
6711 + # ifdef GDB_LVL3_SUPPORT
6712 + /* get source files list */
6713 + this->lvl3.get_source_list = TRUE;
6714 + # endif
6715 + break;
6717 + case CMD_SYMF:
6718 + # ifdef GDB_LVL3_SUPPORT
6719 + /* get source files list */
6720 + this->lvl3.get_source_list = TRUE;
6721 + # endif
6722 + break;
6724 + case CMD_UP:
6725 + case CMD_UP_SILENT:
6726 + case CMD_DOWN:
6727 + case CMD_DOWN_SILENT:
6728 + case CMD_FRAME:
6729 + case CMD_SLECT_FRAME:
6730 + if (this->mode != GDB_MODE_LVL3)
6732 + this->pool.hilite = TRUE;
6734 + /* this should not be necessary but sometimes we
6735 + * don't get the ANO_FRAME_INVALID */
6736 + this->bp_state |= BPS_FR_INVALID;
6738 + break;
6740 + case CMD_DELETE:
6741 + case CMD_DISABLE:
6742 + /* keep BPS_FR_INVALID state */
6743 + this->bp_state &= BPS_FR_INVALID;
6744 + this->bp_state |= BPS_INVALID;
6745 + break;
6747 + /* the restart command is mapped to the gdb 'quit' command,
6748 + * and that will cause gdb to be restarted (the 'quit'
6749 + * command itself is trapped and
6750 + * causes a clean termination of clewn and vim) */
6751 + case CMD_RESTART:
6752 + xfree(cmd);
6753 + cmd = (char_u *)clewn_strsave("quit");
6754 + break;
6756 + /* terminate clewn and vim */
6757 + case CMD_QUIT:
6758 + this->state |= GS_QUITTING;
6759 + break;
6761 + default:
6762 + break;
6764 + xfree(range);
6765 + xfree(delete);
6766 + return cmd;
6769 + /* Send a cmd to gdb */
6770 + void
6771 + gdb_send_cmd(this, cmd)
6772 + gdb_T *this;
6773 + char_u *cmd; /* gdb cmd */
6775 + int do_free = TRUE; /* TRUE when readline must be freed */
6776 + int offset = 0;
6777 + char_u *res;
6778 + char_u *start;
6779 + int len;
6780 + int l;
6782 + if ( ! GDB_STATE(this, GS_UP))
6783 + return;
6785 + this->intr_sent = FALSE;
6787 + /* make a copy so we can mess with it */
6788 + if (cmd == NULL || (len = STRLEN(cmd)) == 0 )
6789 + return;
6790 + cmd = (char_u *)clewn_strsave((char *)cmd);
6792 + /* paranoia: trim after NL */
6793 + if ((res = STRCHR(cmd, (int)NL)) != NULL)
6794 + *(res + 1) = NUL;
6796 + /* answering to a query: any stuff not 'y[es]' is converted to 'no' */
6797 + if (this->cli_cmd.state == CS_QUERY || this->note == ANO_QUERY)
6799 + len = 1;
6800 + if ((res = gdb_regexec(cmd, PAT_YES, 0, NULL)) != NULL)
6802 + *cmd = 'y';
6803 + xfree(res);
6805 + else
6806 + *cmd = 'n';
6808 + # ifdef FEAT_GDB
6809 + /* CMD_DIR is acted upon when parsing gdb output */
6810 + if (this->cmd_type != CMD_DIR)
6811 + this->cmd_type = CMD_ANY;
6812 + # endif
6814 + if (this->cli_cmd.state == CS_QUERY) /* no NL when a completion */
6816 + this->cli_cmd.state = CS_CHOICE;
6817 + do_free = FALSE;
6819 + /* a standalone <Tab> */
6820 + if (this->cli_cmd.readline == NULL
6821 + && this->cli_cmd.gdb != NULL && *(this->cli_cmd.gdb) == NUL)
6822 + this->oob.state &= ~OS_CMD;
6824 + else
6826 + this->cli_cmd.state = CS_START;
6827 + *(cmd + 1) = NL;
6828 + len = 2; /* enough room since cmd length not zero */
6830 + goto write_answer;
6833 + /* an interrupt */
6834 + if (STRCHR(cmd, KEY_INTERUPT) != NULL)
6836 + this->intr_sent = TRUE;
6837 + this->cli_cmd.state = CS_START;
6838 + goto write_answer;
6841 + /* a cmd following a completion response by gdb */
6842 + if (this->cli_cmd.state == CS_DONE && this->cli_cmd.readline != NULL)
6844 + /* readline matches start of cmd: send 'user cmd - readline' */
6845 + if (STRSTR(cmd, this->cli_cmd.readline) == cmd)
6847 + offset = STRLEN(this->cli_cmd.readline);
6848 + len -= offset;
6849 + do_free = FALSE;
6851 + /* no match */
6852 + else
6854 + /* send KEY_KILL to erase gdb's readline */
6855 + gdb_buf[0] = KEY_KILL;
6856 + write(this->fd, gdb_buf, 1);
6858 + /* discard gdb answer:
6859 + * '\r' plus the termcap entry 'ce' (clear to end of line) */
6860 + l = gdb_read(this, (char_u *)gdb_buf, MAX_BUFFSIZE, 1000);
6862 + /* do what the discarded stuff above was meant to do:
6863 + * replace last line by getting rid of readline */
6864 + /* find the rightmost match */
6865 + res = NULL;
6866 + for (start = this->line; *start != NUL; start++)
6867 + if ((start = STRSTR(start, this->cli_cmd.readline)) != NULL)
6868 + res = start;
6869 + else
6870 + break;
6872 + if (res != NULL)
6874 + *res = NUL;
6875 + gdb_write_buf(this, this->line, FALSE);
6877 + FREE(this->cli_cmd.echoed);
6881 + this->cli_cmd.state = CS_START;
6883 + /* a completion request */
6884 + if (*(cmd + offset + len - 1) == TAB)
6886 + this->cli_cmd.state = CS_PENDING;
6888 + xfree(this->cli_cmd.gdb);
6889 + this->cli_cmd.gdb = (char_u *)clewn_strsave((char *)(cmd + offset));
6890 + *(this->cli_cmd.gdb + len - 1) = NUL; /* remove <Tab> */
6892 + write_answer:
6893 + if (do_free)
6894 + FREE(this->cli_cmd.readline);
6895 + write(this->fd, (char *)cmd + offset, len);
6896 + xfree(cmd);
6897 + return;
6900 + # ifdef FEAT_GDB
6901 + # if defined(MACOS_X) || defined(MACOS_X_UNIX)
6902 + /* Strip terminating carriage return from a line */
6903 + static void
6904 + strip_cr(line)
6905 + char_u *line;
6907 + int len = STRLEN(line);
6909 + if (len != 0 && line[len - 1] == '\r')
6910 + line[len - 1] = NUL;
6912 + # endif
6913 + # endif
6915 + # ifndef FEAT_GDB
6916 + /* Handle "prompt-for-continue" annotations.
6917 + * This is not needed by VimGDB as the screen height is very large. */
6918 + # define MANAGE_PRMPT_FORMORE
6920 + /* The fix for writing through readline the concatenation of multiple
6921 + * lines output by gdb, is only correctly implemented for clewn */
6922 + # define FIX_CONCATENATION_WRITE
6923 + # endif
6924 + /*
6925 + * Parse gdb output for annotation and completion. Update gdb console.
6926 + * Return TRUE when the user must be prompted by the input-line window.
6927 + */
6928 + int
6929 + gdb_parse_output_cli(this)
6930 + gdb_T *this;
6932 + # ifdef FIX_CONCATENATION_WRITE
6933 + static int pending_write = FALSE; /* TRUE, this->line content has not been written yet */
6934 + # endif
6935 + struct obstack obs; /* use an obstack for temporary allocated memory */
6936 + char_u *start;
6937 + char_u *end;
6938 + char_u *line;
6939 + char_u *res;
6940 + int rc;
6941 + int len;
6942 + # ifdef MANAGE_PRMPT_FORMORE
6943 + int do_newline;
6944 + # endif
6946 + /* read gdb data */
6947 + if (this == NULL || ! GDB_STATE(this, GS_UP)
6948 + || gdb_read(this, (char_u *)gdb_buf, MAX_BUFFSIZE, 0) <= 0)
6949 + return FALSE;
6951 + (void)obstack_init(&obs);
6953 + /* Process line after line */
6954 + for (start = end = (char_u *)gdb_buf; end != NULL; start = end)
6956 + /* Get next line */
6957 + if ((end = STRCHR(start, NL)) != NULL)
6958 + *end++ = NUL;
6959 + else if (*start == NUL) /* nothing left to read */
6960 + break;
6962 + /* concatenate with incomplete annotation */
6963 + if (this->annotation != NULL)
6965 + obstack_strcat(&obs, this->annotation);
6966 + obstack_strcat0(&obs, start);
6967 + line = (char_u *)obstack_finish(&obs);
6969 + else
6970 + line = obstack_strsave(&obs, start);
6972 + # ifdef FEAT_GDB
6973 + # if defined(MACOS_X) || defined(MACOS_X_UNIX)
6974 + strip_cr(line);
6975 + # endif
6976 + # endif
6978 + /* With GDB 6.0, completion giving as a result a long list of items causes
6979 + * a "--More--" prompt to be issued after what GDB (or readline) considers
6980 + * the height of the terminal (unfortunately not using the GDB height
6981 + * settings). In case we could not size the terminal to a very big height
6982 + * with an ioctl call in exec_gdb(), we must answer to the prompt. */
6983 + if (this->height == 0 /* height not set */
6984 + && this->cli_cmd.state == CS_CHOICE /* a completion list */
6985 + && end == NULL
6986 + && STRCMP(line, "--More--") == 0) /* standalone prompt */
6988 + write(this->fd, " ", 1); /* prompt for more */
6989 + this->annoted = FALSE;
6990 + break;
6993 + # ifdef FEAT_GDB /* Clewn does not use hiliting */
6994 + /* some fuzzy gdb annotation corner: rewrite '(gdb) Quit' so that
6995 + * it gets highlited (must be done before the newline stuff) */
6996 + if (parse_note(this, line) != NULL && this->note == ANO_QUIT)
6997 + gdb_write_buf(this, this->line, FALSE);
6998 + # endif
7000 + /* two consecutive NL: start a new line except when this annotation
7001 + * just follows another annotation
7002 + * IS_ANNOTATION() does not handle a standalone '\032' */
7003 + if (this->newline && (*line != '\032' || !this->annoted))
7005 + # ifdef MANAGE_PRMPT_FORMORE
7006 + do_newline = TRUE;
7008 + /* do not start a new line when parsing annotations and
7009 + * . the next chunk is a "pre-prompt-for-continue" and
7010 + * the previous chunk was an annotation
7011 + * . or this is a "pre-prompt-for-continue" annotation */
7012 + if (this->mode == GDB_MODE_LVL2
7013 + && ! IS_OOBACTIVE(this) && (this->state & GS_ANO))
7015 + if (end != NULL && get_note(this, end) == ANO_PREPMT_FORMORE
7016 + && this->prev_note != ANO_NONE)
7017 + do_newline = FALSE;
7018 + if (line != NULL && get_note(this, line) == ANO_PREPMT_FORMORE)
7019 + do_newline = FALSE;
7022 + if (do_newline)
7023 + # endif
7025 + if (this->line == NULL && *line != '\032')
7027 + if (IS_OOBACTIVE(this))
7028 + gdb_oob_receive(this, (char_u *)"", &obs);
7029 + else
7030 + gdb_write_buf(this, (char_u *)"", TRUE);
7033 + # ifdef FIX_CONCATENATION_WRITE
7034 + if (pending_write)
7035 + gdb_write_buf(this, this->line, TRUE);
7036 + # endif
7038 + FREE(this->line); /* start a new line */
7039 + this->note = ANO_NONE;
7042 + this->newline = FALSE;
7044 + /* Parse for annotations */
7045 + /* we cannot parse "\n\032\032annotation\n" directly
7046 + * as any stuff may be split across two buff read;
7047 + * must concatenate line when interleaved with annotations */
7048 + if (*line == NUL)
7050 + /* ignore echoed NL after ANO_PMT_FORMORE msg */
7051 + if (this->note != ANO_PMT_FORMORE)
7052 + this->newline = TRUE;
7054 + # ifdef MANAGE_PRMPT_FORMORE
7055 + /* start a new line */
7056 + if (this->mode == GDB_MODE_LVL2 && this->prev_note == ANO_POSTPMT_FORMORE)
7058 + FREE(this->line);
7059 + this->note = ANO_NONE;
7061 + # endif
7063 + /* a complete annotation */
7064 + else if (IS_ANNOTATION(line) && end != NULL)
7066 + /* remember last annotation type */
7067 + if (this->note != ANO_PREPMT_FORMORE
7068 + && this->note != ANO_PMT_FORMORE
7069 + && this->note != ANO_POSTPMT_FORMORE)
7070 + this->valid_note = this->note;
7072 + res = parse_note(this, line); /* assert != NULL */
7074 + if ((res = process_annotation(this, res, &obs)) != NULL)
7076 + gdb_setwinput((gdb_handle_T *)this, res);
7077 + xfree(res);
7079 + /* fake an interrupt: will empty stuff and typeahead
7080 + * buffers aborting insert mode, pending mappings
7081 + * and operations */
7082 + got_int = TRUE;
7085 + FREE(this->annotation);
7086 + this->annoted = TRUE;
7088 + # ifdef GDB_LVL2_SUPPORT
7089 + /* ANO_DISP_END has no content and must be trapped here */
7090 + if (
7091 + # ifdef FEAT_GDB
7092 + this->mode == GDB_MODE_LVL2 && this->var_buf != NULL
7093 + # else
7094 + this->mode == GDB_MODE_LVL2 && this->var_buf > 0
7095 + # endif
7096 + && this->note == ANO_DISP_END)
7098 + gdb_process_display(this, (char_u *)"", &obs);
7100 + # endif
7102 + # ifdef MANAGE_PRMPT_FORMORE
7103 + /* start a new line when end of annotation list or table */
7104 + if (this->mode == GDB_MODE_LVL2
7105 + && this->prev_note == ANO_POSTPMT_FORMORE
7106 + && (this->note == ANO_BP_TABLE
7107 + || this->note == ANO_BP_RECORD
7108 + || this->note == ANO_BP_END
7109 + || this->note == ANO_FRAME_END
7110 + || this->note == ANO_DISP_END))
7112 + FREE(this->line); /* start a new line */
7113 + this->note = ANO_NONE;
7115 + # endif
7117 + /* store current annotation type */
7118 + this->prev_note = this->note;
7120 + /* restore annotation type */
7121 + if (this->note == ANO_POSTPMT_FORMORE)
7122 + this->note = this->valid_note;
7124 + /* a partial annotation */
7125 + else if (*line == '\032'
7126 + && (*(line + 1) == NUL || *(line + 1) == '\032')
7127 + && end == NULL)
7129 + xfree(this->annotation);
7130 + this->annotation = (char_u *)clewn_strsave((char *)line);
7131 + break;
7133 + else
7135 + # ifdef MANAGE_PRMPT_FORMORE
7136 + /* The breakpoint table:
7137 + * start a new line when line starts with <TAB>.*/
7138 + if (this->mode == GDB_MODE_LVL2
7139 + && this->prev_note == ANO_POSTPMT_FORMORE
7140 + && line != NULL && *line == TAB)
7142 + FREE(this->line); /* start a new line */
7143 + this->note = ANO_NONE;
7145 + # endif
7147 + if (this->note == ANO_PREPMT_FORMORE)
7149 + # ifdef MANAGE_PRMPT_FORMORE
7150 + if (! IS_OOBACTIVE(this))
7152 + /* Starting with GDB 6.0, GDB sends an ANO_PREPMT_FORMORE
7153 + * whenever ^C have been typed more that gdb_screen_height/2. */
7154 + if (this->state & GS_ANO || this->intr_sent)
7156 + write(this->fd, "\n", 1); /* prompt for more */
7158 + else
7160 + this->oob.state &= ~OS_CMD; /* enable next command */
7161 + xfree(this->prompt);
7162 + if (line != NULL)
7163 + this->prompt = (char_u *)clewn_strsave((char *)line);
7164 + else
7165 + this->prompt = (char_u *)clewn_strsave(
7166 + "---type <return> to continue, or q <return> to quit---");
7168 + this->intr_sent = FALSE;
7170 + # endif
7171 + line = NULL; /* remove ANO_PMT_FORMORE msg */
7174 + # ifdef GDB_LVL2_SUPPORT
7175 + /* handle a display annotation content
7176 + * take care of nested structures and arrays in value content */
7177 + # ifdef FEAT_GDB
7178 + if (this->mode == GDB_MODE_LVL2 && this->var_buf != NULL)
7179 + # else
7180 + if (this->mode == GDB_MODE_LVL2 && this->var_buf > 0)
7181 + # endif
7183 + if ((this->note >= ANO_DISP_BEG && this->note <= ANO_DISP_END)
7184 + || (this->lvl2.doing_value && this->note >= ANO_FIELD_BEG
7185 + && this->note <= ANO_FIELD_END)
7186 + || (this->lvl2.doing_value && this->note >= ANO_ARRAY_BEG
7187 + && this->note <= ANO_ARRAY_END))
7189 + gdb_process_display(this, line, &obs);
7190 + line = NULL;
7193 + # endif
7195 + if (IS_OOBACTIVE(this))
7197 + gdb_oob_receive(this, line, &obs);
7199 + else
7201 + if (this->note == ANO_PROMPT || this->note == ANO_CMDS)
7202 + gdb_cat(&(this->cli_cmd.echoed), line);
7204 + /* update line cnt before doing cpltn */
7205 + if (this->line == NULL || !this->annoted)
7206 + this->cli_cmd.cnt++;
7208 + /* Parse for completion */
7209 + if ((res = process_completion( &(this->cli_cmd), line, &obs)) != NULL)
7211 + gdb_setwinput((gdb_handle_T *)this, res);
7212 + xfree(res);
7213 + got_int = TRUE;
7216 + if (line != NULL && (len = STRLEN(line)) != 0
7217 + && *(line + len - 1) == BELL)
7218 + *(line + len - 1) = NUL;
7220 + /* concatenate after an annotation and replace, otherwise add */
7221 + if (this->line != NULL && this->annoted)
7223 + if (this->note == ANO_ERROR_BEG && STRCMP(line, "Quit") == 0)
7224 + this->syntax = TRUE;
7226 + obstack_strcat(&obs, this->line);
7227 + obstack_strcat0(&obs, line);
7228 + line = (char_u *)obstack_finish(&obs);
7230 + # ifndef FEAT_GDB /* do not write "(gdb) Quit" with Clewn (already done) */
7231 + if (this->note != ANO_ERROR_BEG)
7232 + # endif
7234 + # ifdef FIX_CONCATENATION_WRITE
7235 + /* write a complete line */
7236 + if (end != NULL)
7238 + if (pending_write)
7239 + gdb_write_buf(this, line, TRUE);
7240 + else
7241 + gdb_write_buf(this, line, FALSE);
7243 + # else
7244 + gdb_write_buf(this, line, FALSE);
7245 + # endif
7249 + else
7251 + # ifdef FEAT_GDB /* no need to map T_CE when running Clewn */
7252 + /* a completion list */
7253 + if (this->height == 0 /* height not set */
7254 + && this->cli_cmd.state == CS_CHOICE)
7256 + char_u *ptr;
7258 + /* discard "^\rT_CE\r" which is sent by readline
7259 + * after answering to a prompt in a completion list
7260 + * (not needed on systems where TIOCSWINSZ ioctls are
7261 + * available) */
7262 + if (STRSTR(line, T_CE) == line + 1
7263 + && STRLEN(line) >= STRLEN(T_CE) + 2)
7265 + ptr = line + STRLEN(T_CE) + 2;
7266 + line = obstack_strsave(&obs, ptr);
7269 + gdb_write_buf(this, line, TRUE);
7270 + # else
7271 + /* do not write the query prompt */
7272 + if (this->cli_cmd.state == CS_QUERY)
7273 + gdb_write_buf(this, (char_u *)"", TRUE);
7274 + else
7276 + # ifdef FIX_CONCATENATION_WRITE
7277 + /* write a complete line */
7278 + if (end != NULL)
7280 + gdb_write_buf(this, line, TRUE);
7282 + # else
7283 + gdb_write_buf(this, line, TRUE);
7284 + # endif
7286 + # endif
7289 + xfree(this->line);
7290 + this->line = (line != NULL ? (char_u *)clewn_strsave((char *)line) : NULL);
7293 + # ifdef FIX_CONCATENATION_WRITE
7294 + pending_write = FALSE;
7295 + if (end == NULL) /* incomplete line */
7297 + pending_write = TRUE;
7298 + this->annoted = TRUE; /* force concatenation on next read */
7299 + break;
7301 + # else
7302 + if (end == NULL) /* incomplete line */
7304 + this->annoted = TRUE; /* force concatenation on next read */
7305 + break;
7307 + # endif
7308 + this->annoted = FALSE;
7309 + this->note = ANO_NONE;
7311 + } /* for (...) */
7313 + obstack_free(&obs, NULL);
7315 + if (IS_OOBACTIVE(this))
7316 + return FALSE;
7318 + # ifdef FEAT_GDB
7319 + /* redraw gdb console window when displayed */
7320 + gdb_redraw(this->buf);
7321 + # endif
7323 + /* Wait till we get the prompt to send the first cmd */
7324 + if (this->firstcmd != NULL && this->note == ANO_PROMPT)
7326 + gdb_docmd((gdb_handle_T *)this, this->firstcmd);
7327 + FREE(this->firstcmd);
7330 + if ((rc = gdb_iswinput((gdb_handle_T *)this)) == TRUE)
7331 + this->oob.state &= ~OS_CMD;
7332 + return rc;
7335 + /*
7336 + * Process an annotation.
7337 + * Return cmd to prompt the user with or NULL if none.
7338 + */
7339 + static char_u *
7340 + process_annotation(this, str, obs)
7341 + gdb_T *this;
7342 + char_u *str; /* annotation's content */
7343 + struct obstack *obs;
7345 + int s_a = (this->state & GS_ALLOWED);
7346 + char_u *file = NULL;
7347 + char_u *line = NULL;
7348 + linenr_T linenumber;
7349 + char_u *cpn;
7350 + int bp_number;
7351 + bpinfo_T *r;
7353 + this->syntax = FALSE;
7354 + this->parser = PS_ANY;
7356 + switch (this->note)
7358 + /* Output end: run directory function */
7359 + case ANO_PREPROMPT:
7360 + this->syntax = TRUE;
7361 + this->parser = PS_PREPROMPT;
7362 + this->cmd_type = CMD_ANY;
7363 + this->state &= ~GS_ANO;
7364 + break;
7366 + /* Send out of band cmd */
7367 + case ANO_PROMPT:
7368 + this->syntax = TRUE;
7369 + this->parser = PS_PROMPT;
7370 + this->cli_cmd.cnt = 1;
7371 + FREE(this->cli_cmd.echoed);
7372 + # ifndef FEAT_GDB /* store the prompt */
7373 + if (! IS_OOBACTIVE(this) || (this->oob.state & OS_INTR))
7375 + xfree(this->prompt);
7376 + if (this->line != NULL)
7377 + this->prompt = (char_u *)clewn_strsave((char *)this->line);
7378 + else
7379 + this->prompt = (char_u *)clewn_strsave("(gdb) ");
7381 + # endif
7382 + if (this->cli_cmd.state == CS_START) {
7383 + gdb_oob_send(this, obs);
7385 + /* reset the standard oobfunc table after invocation
7386 + * of a one function oobfunc array */
7387 + this->oobfunc = this->std_oobfunc;
7389 + break;
7391 + case ANO_CMDS:
7392 + this->syntax = TRUE;
7393 + this->cli_cmd.cnt = 1;
7394 + this->oob.state &= ~OS_CMD;
7395 + FREE(this->cli_cmd.echoed);
7396 + # ifndef FEAT_GDB /* store the prompt */
7397 + if (! IS_OOBACTIVE(this) || (this->oob.state & OS_INTR))
7399 + xfree(this->prompt);
7400 + if (this->line != NULL)
7401 + this->prompt = (char_u *)clewn_strsave((char *)this->line);
7402 + else
7403 + this->prompt = (char_u *)clewn_strsave("> ");
7405 + # endif
7407 + /* should be in process_completion, but bug in gdb
7408 + * annotations where 'pre-commands' is missing in completions */
7409 + if (this->cli_cmd.state == CS_CHOICE
7410 + && (cpn = eol_choices(&(this->cli_cmd), obs)) != NULL)
7411 + return cpn;
7413 + /* a lone <Tab> does not prompt the user except in define mode */
7414 + if ((this->cli_cmd.state != CS_PENDING
7415 + && this->cli_cmd.state != CS_CHOICE)
7416 + || (this->cli_cmd.readline == NULL && this->cli_cmd.gdb != NULL
7417 + && *(this->cli_cmd.gdb) == NUL))
7418 + return (char_u *)clewn_strsave("");
7419 + break;
7421 + case ANO_OVERLOAD:
7422 + case ANO_QUERY:
7423 + this->oob.state &= ~OS_CMD;
7424 + # ifndef FEAT_GDB /* store the prompt */
7425 + if (! IS_OOBACTIVE(this) || (this->oob.state & OS_INTR))
7427 + xfree(this->prompt);
7428 + if (this->line != NULL)
7429 + this->prompt = (char_u *)clewn_strsave((char *)this->line);
7430 + else
7431 + this->prompt = (char_u *)clewn_strsave("> ");
7433 + # endif
7434 + return (char_u *)clewn_strsave("");
7436 + case ANO_PMT_FORMORE:
7437 + # ifndef FEAT_GDB /* handle ANO_PMT_FORMORE when IS_OOBACTIVE */
7438 + if (IS_OOBACTIVE(this))
7439 + # endif
7441 + if (this->oob.state & OS_INTR)
7443 + clewn_beep();
7444 + gdb_send_cmd(this, (char_u *)"q\n"); /* abort */
7446 + else
7447 + gdb_send_cmd(this, (char_u *)"\n"); /* get more lines */
7449 + break;
7451 + case ANO_QUIT:
7452 + this->syntax = TRUE;
7453 + this->oob.state |= OS_QUIT;
7454 + break;
7456 + case ANO_ERROR_BEG:
7457 + this->pool.hilite = FALSE;
7458 + # ifdef GDB_LVL2_SUPPORT
7459 + /* a display expression parse error */
7460 + this->lvl2.doing_value = FALSE;
7461 + FREE(this->lvl2.dentry.num);
7462 + FREE(this->lvl2.dentry.expression);
7463 + FREE(this->lvl2.dentry.value);
7464 + # endif
7465 + # ifdef GDB_LVL3_SUPPORT
7466 + if (this->lvl3.varitem != NULL)
7467 + this->lvl3.varitem->state |= VS_ERROR;
7468 + # endif
7469 + break;
7471 + case ANO_STARTING:
7472 + this->frame_curlvl = -1;
7473 + this->frame_lnum = (linenr_T) -1;
7474 + FREE(this->frame_fname);
7476 + FREE(this->frame_pc);
7477 + this->state &= ~GS_STOPPED;
7478 + gdb_status(this, (char_u *)"running...", obs);
7480 + if (this->mode == GDB_MODE_LVL3)
7482 + this->pool.hilite = FALSE;
7483 + if (p_asm != 0 && this->cmd_type == CMD_STEPI) /* asm frame highlite: when stepi nexti */
7484 + this->pool.hilite = TRUE;
7486 + else
7488 + this->pool.hilite = TRUE;
7490 + case ANO_FRAME_INVALID:
7491 + gdb_fr_unlite(this);
7492 + this->bp_state |= BPS_FR_INVALID;
7493 + break;
7495 + case ANO_BP_INVALID:
7496 + /* keep BPS_FR_INVALID state */
7497 + this->bp_state &= BPS_FR_INVALID;
7498 + this->bp_state |= BPS_INVALID;
7500 + /* note the fact that the user is setting a
7501 + * breakpoint */
7502 + if (p_asm != 0 && this->cmd_type == CMD_BREAK)
7503 + this->bp_state |= BPS_BP_SET;
7504 + break;
7506 + case ANO_STOPPED:
7507 + this->state |= GS_STOPPED;
7508 + gdb_status(this, (char_u *)"stopped", obs);
7509 + # ifdef GDB_LVL2_SUPPORT
7510 + # ifdef FEAT_GDB
7511 + if (this->var_buf != NULL)
7512 + # else
7513 + if (this->var_buf > 0)
7514 + # endif
7515 + this->lvl2.varlist.state = DSP_STOPPED;
7516 + # endif
7517 + break;
7519 + case ANO_EXITED:
7520 + case ANO_SIGNALLED:
7521 + FREE(this->frame_pc);
7523 + this->state |= GS_STOPPED;
7524 + gdb_status(this, (char_u *)"exited", obs);
7526 + # ifdef FEAT_GDB
7527 + /* remove phantom highlite */
7528 + gdb_unlite(PHANTOM_SIGN);
7529 + # endif
7530 + break;
7532 + /* Breakpoint hit */
7533 + case ANO_BREAKPOINT:
7534 + /* Look for this breakpoint in bpinfo list */
7535 + if (str != NULL && (bp_number = atoi((char *)str)) > 0)
7537 + for (r = this->bpinfo; r != NULL; r = r->next)
7539 + if (r->id == bp_number)
7541 + /* Set this->cont TRUE if this breakpoint's 'commands'
7542 + * includes a 'continue' as last statement */
7543 + if (r->cont)
7544 + this->cont = TRUE;
7546 + # ifdef BP_INVALID_ANO_MISSING
7547 + /* Trigger get_bp(): the breakpoint we hit is
7548 + * 'enable once' */
7549 + if (r->enabled && ! r->disposition)
7551 + /* keep BPS_FR_INVALID state */
7552 + this->bp_state &= BPS_FR_INVALID;
7553 + this->bp_state |= BPS_INVALID | BPS_BP_HIT;
7555 + # endif
7556 + break;
7560 + /* Not found in the list. An asm buffer holding this bp
7561 + * can possibly be disassembled next by oob get_asm().
7562 + * Trigger oob get_bp() */
7563 + if (r == NULL && p_asm != 0)
7565 + /* keep BPS_FR_INVALID state */
7566 + this->bp_state &= BPS_FR_INVALID;
7567 + this->bp_state |= BPS_INVALID | BPS_BP_HIT;
7570 + break;
7572 + # ifdef GDB_LVL2_SUPPORT
7573 + case ANO_SOURCE:
7574 + /* gdb stats the file when doing ANO_SOURCE, so we can't rely on
7575 + * that annotation for remote debugging with clewn when the source
7576 + * files are on the host and not on the target
7577 + * => use ANO_BREAKPOINT instead in level 3
7578 + */
7580 + if (! IS_OOBACTIVE(this) && this->mode == GDB_MODE_LVL2)
7582 + /* Uncomment next line to print source text in gdb buffer */
7583 + /* gdb_write_buf(this, str, TRUE); */
7585 + # ifdef FEAT_GDB
7586 + gdb_popup_console(this);
7587 + # endif
7589 + this->pool.hilite = FALSE;
7591 + /* asm frame highlite: when stepi nexti */
7592 + if (p_asm != 0 && this->cmd_type == CMD_STEPI)
7593 + this->pool.hilite = TRUE;
7594 + else
7596 + /* prevent recursive calls to parse_output() since breakpoint
7597 + * or frame highlighting may cause Vim to query the user when
7598 + * changes have been made in the previous buffer */
7599 + this->state &= ~GS_ALLOWED;
7601 + if ((line = gdb_regexec(str, PAT_SOURCE, 2, obs)) != NULL)
7603 + file = gdb_regexec(str, PAT_SOURCE, 1, obs);
7604 + linenumber = atoi((char *)line);
7605 + gdb_fr_set(this, file, &linenumber, obs);
7608 + this->state &= ~GS_ALLOWED;
7609 + if (s_a)
7610 + this->state |= GS_ALLOWED;
7613 + break;
7615 + case ANO_FRAME_BEGIN:
7616 + case ANO_BP_HEADER:
7617 + case ANO_DISP_BEG:
7618 + this->state |= GS_ANO;
7619 + break;
7621 + case ANO_FRAME_END:
7622 + case ANO_DISP_END:
7623 + break;
7625 + /* Get the source for this frame */
7626 + case ANO_BP_RECORD:
7627 + this->bp_state |= BPS_RECORD;
7628 + this->bp_state |= BPS_START;
7629 + break;
7631 + case ANO_BP_FIELD0:
7632 + case ANO_BP_FIELD1:
7633 + case ANO_BP_FIELD2:
7634 + case ANO_BP_FIELD3:
7635 + case ANO_BP_FIELD4:
7636 + case ANO_BP_FIELD5:
7637 + case ANO_BP_FIELD6:
7638 + case ANO_BP_FIELD7:
7639 + case ANO_BP_FIELD8:
7640 + case ANO_BP_FIELD9:
7641 + this->bp_state = SET_RECORD_IDX(this->bp_state,
7642 + (this->note - ANO_BP_FIELD0) + BI_NUM);
7643 + break;
7645 + case ANO_BP_END:
7646 + /* Initialize state but do not forget some of them.
7647 + * ANO_BP_END can be the one we get when fetching the
7648 + * table with oob function get_lastbp(): get_bp() still
7649 + * needs those states */
7650 + this->bp_state &= (BPS_INVALID | BPS_BP_HIT | BPS_FR_INVALID);
7651 + break;
7652 + # endif
7654 + return NULL;
7657 + /*
7658 + * Parse gdb output for completion.
7659 + * Return cmd to prompt the user with or NULL if none.
7660 + */
7661 + static char_u *
7662 + process_completion(cmd, line, obs)
7663 + cli_cmd_T *cmd;
7664 + char_u *line; /* line to parse */
7665 + struct obstack *obs;
7667 + char_u *res;
7668 + char_u *start;
7669 + int len;
7671 + if (line == NULL || *line == NUL)
7672 + return NULL;
7674 + switch (cmd->state)
7676 + case CS_PENDING:
7677 + /* A completion query */
7678 + if (cmd->cnt == 2 && gdb_regexec(line, PAT_QUERY, 0, obs) != NULL)
7680 + cmd->state = CS_QUERY;
7681 + return (char_u *)clewn_strsave("");
7684 + /* A positive completion */
7685 + if (cmd->cnt == 1 && cmd->echoed != NULL
7686 + && (len = (cmd->gdb != NULL ? STRLEN(cmd->gdb) : 0)) > 0)
7688 + /* find the rightmost match */
7689 + res = NULL;
7690 + for (start = cmd->echoed; *start != NUL; start++)
7691 + if ((start = STRSTR(start, cmd->gdb)) != NULL)
7692 + res = start;
7693 + else
7694 + break;
7696 + /* strictly greater and not followed by NL */
7697 + if (res != NULL && *(res + len) != NL
7698 + && cmd->echoed + STRLEN(cmd->echoed) > res + len)
7700 + if (*(res + len) == BELL)
7702 + clewn_beep();
7703 + *(res + len) = NUL;
7705 + xfree(cmd->readline);
7706 + cmd->readline = (char_u *)clewn_strsave((char *)cmd->echoed);
7707 + cmd->state = CS_DONE;
7708 + return (char_u *)clewn_strsave((char *)cmd->readline);
7712 + /* A BELL: first character */
7713 + if (cmd->cnt == 1 && *line == BELL)
7715 + *line = NUL;
7716 + clewn_beep();
7717 + cmd->state = CS_DONE;
7718 + return (cmd->readline != NULL ?
7719 + (char_u *)clewn_strsave((char *)cmd->readline) : NULL);
7722 + if (cmd->cnt > 1)
7723 + cmd->state = CS_CHOICE;
7724 + break;
7726 + case CS_CHOICE:
7727 + /* The end of a list of completion choices */
7728 + if (cmd->cnt == 1 && (res = eol_choices(cmd, obs)) != NULL)
7729 + return res;
7730 + break;
7732 + return NULL;
7735 + /*
7736 + * The end of a list of completion choices.
7737 + * Return cmd to prompt the user with.
7738 + */
7739 + static char_u *
7740 + eol_choices(cmd, obs)
7741 + cli_cmd_T *cmd;
7742 + struct obstack *obs;
7744 + char_u *new;
7746 + obstack_strcat(obs, cmd->readline);
7747 + obstack_strcat0(obs, cmd->gdb);
7748 + new = (char_u *)obstack_finish(obs);
7750 + /* a match with the new readline */
7751 + if (cmd->echoed != NULL && STRSTR(cmd->echoed, new) == cmd->echoed)
7753 + xfree(cmd->readline);
7754 + cmd->readline = (char_u *)clewn_strsave((char *)cmd->echoed);
7755 + cmd->state = CS_DONE;
7756 + return (char_u *)clewn_strsave((char *)cmd->echoed);
7758 + return NULL;
7761 + # ifdef GDB_LVL3_SUPPORT
7762 + /* Initialize the gdb_T structure lvl3 component that lvl3 is responsible for */
7763 + static void
7764 + clear_gdb_T(this)
7765 + gdb_T *this;
7767 + varobj_T *item, *next;
7769 + if (this != NULL)
7771 + FREE(this->lvl3.result);
7773 + this->lvl3.get_source_list = TRUE;
7774 + FREE(this->lvl3.source_cur);
7775 + FREE(this->lvl3.source_list);
7777 + for (item = this->lvl3.varlist; item != NULL; item = next)
7779 + next = item->next;
7780 + xfree(item->name);
7781 + xfree(item->format);
7782 + xfree(item->expression);
7783 + xfree(item);
7785 + this->lvl3.varlist = NULL;
7786 + this->lvl3.varitem = NULL;
7790 + /* Initialize lvl3 function pointers */
7791 + void
7792 + gdb_lvl3_init(this)
7793 + gdb_T *this;
7795 + this->mode = GDB_MODE_LVL3;
7796 + this->oobfunc = oobfunc;
7797 + this->std_oobfunc = oobfunc;
7798 + this->parse_output = gdb_parse_output_cli;
7799 + this->gdb_docmd = gdb_docmd_cli;
7800 + this->var_delete = NULL;
7801 + this->clear_gdb_T = clear_gdb_T;
7803 + # endif /* GDB_LVL3_SUPPORT */
7805 + # ifdef FEAT_GDB
7806 + # define SG_INTRO_2 "Vim |+gdb| level 2 mode\n\n"
7807 + # define SG_INTRO_3 "Vim |+gdb| level 3 mode\n\n"
7808 + # else
7809 + # define SG_INTRO_2 "... \
7810 + \n... Clewn running GDB in level 2 mode\n...\n"
7811 + # define SG_INTRO_3 "... \
7812 + \n... Clewn %s running GDB in level 3 mode\n...\n"
7813 + # endif
7814 + # define SG_INTERP "server interpreter-exec mi -gdb-version\n"
7815 + # define SG_LVL_2 "server set annotate 2\n"
7816 + # define SG_LVL_3 "server set annotate 3\n"
7817 + # define SG_HEIGHT "server set height "
7818 + # define SG_WIDTH "server set width 0\n "
7819 + # define SG_EDITING "server set editing on\n"
7820 + # define SG_VERSION "server show version\n"
7822 + /* SG_TIMEOUT must be quite big as we may have Clewn, Vim and GDB all
7823 + * starting at the same time. Unless things go pretty bad in the parsing, we
7824 + * always find the needle, so the user never wait SG_TIMEOUT. */
7825 + # define SG_TIMEOUT 120000 /* msecs for when the needle cannot be found */
7826 + /*
7827 + * Initialize gdb CLI (command line interface)
7828 + * return OK when sucess, FAIL otherwise
7829 + */
7830 + int
7831 + gdb_setup_cli(this)
7832 + gdb_T *this;
7834 + char *err = NULL;
7835 + int needle = FALSE; /* defines when we can start writing to gdb console */
7836 + int gdb_cnt = 0; /* count of received "(gdb)" prompts */
7837 + int lvl3_mode = FALSE; /* level */
7838 + char_u *buff = (char_u *)gdb_buf;/* can't add an int to the reference to an array */
7839 + char * tty_name = NULL;
7840 + # ifndef FEAT_GDB
7841 + char tmp[128];
7842 + # endif
7843 + char_u *last;
7844 + char_u *ptr;
7845 + char_u *lpp_lines;
7846 + char_u *line;
7847 + int len;
7849 + this->note = ANO_NONE;
7851 + /* Does this GDB process supports "interpreter-exec" command ?
7852 + * if yes we will use level 3 mode, otherwise level 2 mode */
7853 + write(this->fd, SG_INTERP, strlen(SG_INTERP));
7855 + /* discard gdb output till we find the needle SG_VERSION
7856 + * MAX_BUFFSIZE must be greater than max gdb line length */
7857 + for (last = (char_u *)gdb_buf; buff + MAX_BUFFSIZE - last > 1; )
7859 + if ((len = gdb_read(this, last,
7860 + buff + MAX_BUFFSIZE - last, SG_TIMEOUT)) < 0)
7862 + err = "Unable to read from GDB pseudo tty";
7863 + goto fail;
7865 + else if (len == 0) /* needle not found */
7866 + break;
7868 + last += len;
7869 + ptr = (char_u *)gdb_buf;
7871 + /* First step: determine which level, process line by line */
7872 + do
7874 + if (gdb_cnt >= 2)
7875 + break;
7877 + if (*ptr == NL)
7878 + ptr++;
7880 + if (STRSTR(ptr, "^done") == ptr)
7881 + lvl3_mode = TRUE;
7883 + /* the first prompt is newline terminated (count it only once) */
7884 + if (STRSTR(ptr, "(gdb) ") == ptr
7885 + && (gdb_cnt == 1 || STRCHR(ptr, NL) != NULL))
7886 + gdb_cnt++;
7888 + if (gdb_cnt == 2)
7890 + # ifdef GDB_LVL3_SUPPORT
7891 + /* set annotation level 3 */
7892 + if (lvl3_mode)
7893 + write(this->fd, SG_LVL_3, strlen(SG_LVL_3));
7894 + else
7895 + # ifdef GDB_LVL2_SUPPORT
7896 + write(this->fd, SG_LVL_2, strlen(SG_LVL_2));
7897 + # else
7899 + err = "This |+gdb| version does not support level 2 mode";
7900 + goto fail;
7902 + # endif
7903 + # else /* LVL3 */
7904 + lvl3_mode = FALSE;
7905 + # ifdef GDB_LVL2_SUPPORT
7906 + /* set annotation level 2 */
7907 + if (! lvl3_mode)
7908 + write(this->fd, SG_LVL_2, strlen(SG_LVL_2));
7909 + # endif
7910 + # endif /* LVL3 */
7912 + # ifdef FEAT_GDB /* Clewn does not need this */
7913 + /* ANO_PMT_FORMORE happen every LPP_LINES and provide us a mean to abort
7914 + * large output (in get_asm for example or any user cmd) */
7915 + write(this->fd, SG_HEIGHT, strlen(SG_HEIGHT));
7916 + lpp_lines = gdb_itoa(LPP_LINES);
7917 + write(this->fd, (char *)lpp_lines, strlen((char *)lpp_lines));
7918 + write(this->fd, "\n", 1);
7919 + write(this->fd, SG_WIDTH, strlen(SG_WIDTH));
7920 + write(this->fd, SG_EDITING, strlen(SG_EDITING));
7921 + # else
7922 + /* number of lines in a page is unlimited */
7923 + write(this->fd, SG_HEIGHT, strlen(SG_HEIGHT));
7924 + lpp_lines = gdb_itoa(0);
7925 + write(this->fd, lpp_lines, strlen(lpp_lines));
7926 + write(this->fd, "\n", 1);
7927 + write(this->fd, SG_WIDTH, strlen(SG_WIDTH));
7928 + write(this->fd, SG_EDITING, strlen(SG_EDITING));
7929 + write(this->fd, " \n", 2); /* avoid Undefined command: "server". Try "help". */
7931 + /* `run' commands do input and output on clewn own terminal when possible */
7932 + if (isatty(1) && (tty_name=ttyname(1)) != NULL) {
7933 + char_u * res = NULL;
7935 + gdb_cat(&res, (char_u *)"server tty ");
7936 + gdb_cat(&res, tty_name);
7937 + gdb_cat(&res, (char_u *)"\n");
7938 + write(this->fd, res, STRLEN(res));
7939 + xfree(res);
7941 + # endif
7942 + write(this->fd, SG_VERSION, strlen(SG_VERSION));
7944 + } while ((ptr = STRCHR(ptr, NL)) != NULL);
7946 + /* Second step: find the needle, process line by line */
7947 + do
7949 + if (ptr == NULL)
7950 + break;
7952 + if (*ptr == NL)
7953 + ptr++;
7955 + /* looking for the needle after a prompt */
7956 + if (this->note == ANO_PROMPT && STRSTR(ptr, SG_VERSION) == ptr)
7958 + ptr += strlen(SG_VERSION);
7959 + needle = TRUE;
7962 + /* discard post-prompt */
7963 + if (needle && this->note == ANO_POSTPROMPT)
7965 + /* store a partial last line for later parse_output */
7966 + if ((line = (char_u *)strrchr(gdb_buf, (int)NL)) != NULL
7967 + && *(line + 1) != NUL)
7969 + xfree(this->line);
7970 + this->line = (char_u *)clewn_strsave((char *)(line + 1));
7971 + this->annoted = TRUE;
7974 + if (lvl3_mode)
7975 + # ifdef GDB_LVL3_SUPPORT
7977 + # ifdef FEAT_GDB
7978 + gdb_popup_console(this);
7979 + # endif
7981 + this->syntax = TRUE; /* force syntax highlite */
7982 + # ifdef FEAT_GDB
7983 + gdb_write_buf(this, (char_u *)SG_INTRO_3, TRUE);
7984 + # else
7985 + sprintf(tmp, SG_INTRO_3, this->version);
7986 + gdb_write_buf(this, tmp, TRUE);
7987 + # endif
7988 + this->syntax = FALSE;
7990 + # ifdef FEAT_GDB /* write unconditionally with Clewn */
7991 + /* write the remaining part and display it */
7992 + if (*ptr != NUL)
7993 + # endif
7994 + gdb_write_buf(this, ptr, TRUE);
7996 + # ifdef FEAT_GDB
7997 + /* redraw gdb console window when displayed */
7998 + gdb_redraw(this->buf);
7999 + # endif
8001 + gdb_lvl3_init(this);
8003 + # else
8005 + err = "This |+gdb| version does not support level 3 mode";
8006 + goto fail;
8008 + # endif
8009 + else
8010 + # ifdef GDB_LVL2_SUPPORT
8012 + # ifdef FEAT_GDB
8013 + gdb_popup_console(this);
8014 + # endif
8016 + this->syntax = TRUE; /* force syntax highlite */
8017 + gdb_write_buf(this, (char_u *)SG_INTRO_2, TRUE);
8018 + this->syntax = FALSE;
8020 + # ifdef FEAT_GDB /* write unconditionally with Clewn */
8021 + /* write the remaining part and display it */
8022 + if (*ptr != NUL)
8023 + # endif
8024 + gdb_write_buf(this, ptr, TRUE);
8026 + # ifdef FEAT_GDB
8027 + /* redraw gdb console window when displayed */
8028 + gdb_redraw(this->buf);
8029 + # endif
8031 + gdb_lvl2_init(this);
8033 + # else
8035 + err = "This |+gdb| version does not support level 2 mode";
8036 + goto fail;
8038 + # endif
8039 + if (tty_name)
8040 + fprintf(stderr, "`run' commands do input and output on the terminal %s\n", tty_name);
8042 + return OK;
8044 + } while ((ptr = parse_note(this, ptr)) != NULL);
8046 + /* left shift buffer to last start of line */
8047 + if ((ptr = (char_u *)strrchr((char *)gdb_buf, (int)NL)) != NULL)
8049 + len = STRLEN(ptr + 1);
8050 + clewn_memmove(gdb_buf, ptr + 1, len);
8051 + last = (char_u *)gdb_buf + len;
8055 + # ifdef GDB_LVL2_SUPPORT
8056 + /* could not find the needle: hope for the best and fall back
8057 + * to annotation level 2 and send version again */
8058 + write(this->fd, SG_LVL_2, strlen(SG_LVL_2));
8059 + write(this->fd, SG_VERSION, strlen(SG_VERSION));
8060 + # ifdef FEAT_GDB
8061 + gdb_popup_console(this);
8062 + # endif
8064 + this->syntax = TRUE; /* force syntax highlite */
8065 + gdb_write_buf(this, (char_u *)SG_INTRO_2, TRUE);
8066 + this->syntax = FALSE;
8068 + gdb_lvl2_init(this);
8069 + return OK;
8070 + # else
8071 + err = "This |+gdb| version does not support level 2 mode";
8072 + goto fail;
8073 + # endif
8074 + fail:
8075 + gdb_close(this);
8077 + if (err != NULL)
8078 + EMSG(_(err));
8080 + return FAIL;
8083 + # ifdef GDB_LVL3_SUPPORT
8084 + /* Print a value in a netbeans balloon */
8085 + # define PRINT_VALUE "^done,value=\""
8086 + char *
8087 + gdb_print_value(this, state, line, obs)
8088 + gdb_T *this;
8089 + int state;
8090 + char_u *line;
8091 + struct obstack *obs;
8093 + # ifdef HAVE_CLEWN
8094 + char_u * res = NULL;
8095 + char_u * ptr;
8096 + char_u * quote;
8098 + switch(state)
8100 + case OOB_CMD:
8101 + if (this->balloon_txt != NULL) {
8102 + obstack_strcat(obs, "server interpreter-exec mi \"-data-evaluate-expression ");
8103 + obstack_strcat(obs, this->balloon_txt);
8104 + obstack_strcat0(obs, "\"\n");
8106 + FREE(this->lvl3.result);
8107 + return (char_u *)obstack_finish(obs);
8109 + break;
8111 + case OOB_COLLECT:
8112 + gdb_cat(&res, this->lvl3.result);
8113 + gdb_cat(&res, line);
8114 + xfree(this->lvl3.result);
8115 + this->lvl3.result = res;
8116 + break;
8118 + case OOB_COMPLETE:
8119 + if (this->lvl3.result != NULL
8120 + && (ptr = STRSTR(this->lvl3.result, PRINT_VALUE)) != NULL
8121 + && (ptr += strlen(PRINT_VALUE))
8122 + && (quote = (char_u *)strrchr(ptr, '"')) != NULL)
8124 + *quote = NUL;
8125 + obstack_strcat(obs, "\" ");
8126 + obstack_strcat(obs, this->balloon_txt);
8127 + obstack_strcat(obs, " = ");
8128 + obstack_strcat(obs, ptr);
8129 + obstack_strcat0(obs, " \"");
8131 + res = (char_u *)obstack_finish(obs);
8132 + gdb_showBalloon(res, obs);
8135 + FREE(this->balloon_txt);
8136 + FREE(this->lvl3.result);
8137 + break;
8139 + # endif /* HAVE_CLEWN*/
8140 + return NULL;
8142 + # endif /* GDB_LVL3_SUPPORT */
8144 + /* Get instruction at $pc */
8145 + char *
8146 + gdb_get_pc(this, state, line, obs)
8147 + gdb_T *this;
8148 + int state;
8149 + char_u *line;
8150 + struct obstack *obs;
8152 + char_u *ptr;
8154 + if (obs) {} /* keep compiler happy */
8156 + switch(state)
8158 + case OOB_CMD:
8159 + FREE(this->pc);
8161 + if (this->state & GS_STOPPED)
8163 + this->state &= ~GS_STOPPED;
8164 + return "server x/i $pc\n";
8166 + break;
8168 + case OOB_COLLECT:
8169 + if ((this->pc = gdb_regexec(line, PAT_ADD, 1, NULL)) != NULL)
8171 + /* Replace TAB with a space */
8172 + for (ptr = line; *ptr != NUL; ptr++)
8173 + if (*ptr == TAB)
8174 + *ptr = ' ';
8176 + gdb_status(this, line, obs);
8178 + break;
8180 + return NULL;
8183 + /* Get frame info */
8184 + char *
8185 + gdb_get_frame(this, state, line, obs)
8186 + gdb_T *this;
8187 + int state;
8188 + char_u *line;
8189 + struct obstack *obs;
8191 + char_u *res = NULL;
8193 + if (obs) {} /* keep compiler happy */
8195 + switch(state)
8197 + case OOB_CMD:
8198 + FREE(this->oob_result);
8199 + return "server frame\n";
8201 + case OOB_COLLECT:
8202 + gdb_cat(&res, this->oob_result);
8203 + gdb_cat(&res, line);
8204 + xfree(this->oob_result);
8205 + this->oob_result = res;
8206 + break;
8208 + case OOB_COMPLETE:
8209 + xfree(this->frame_pc);
8210 + if (this->oob_result != NULL
8211 + && (this->frame_pc = gdb_regexec(this->oob_result, PAT_FRAME, 1, NULL)) != NULL) {
8212 + xfree(this->asm_add);
8213 + this->asm_add = (char_u *)clewn_strsave((char *)this->frame_pc);
8215 + else {
8216 + if (this->pc != NULL) {
8217 + this->frame_pc = (char_u *)clewn_strsave((char *)this->pc);
8218 + xfree(this->asm_add);
8219 + this->asm_add = (char_u *)clewn_strsave((char *)this->frame_pc);
8223 + FREE(this->oob_result);
8224 + break;
8226 + return NULL;
8229 + # ifdef GDB_LVL3_SUPPORT
8230 + /* Stack info frame */
8231 + char *
8232 + gdb_info_frame(this, state, line, obs)
8233 + gdb_T *this;
8234 + int state;
8235 + char_u *line;
8236 + struct obstack *obs;
8238 + char_u *res = NULL;
8240 + if (obs) {} /* keep compiler happy */
8242 + switch(state)
8244 + case OOB_CMD:
8245 + FREE(this->lvl3.result);
8246 + return "server info frame\n";
8248 + case OOB_COLLECT:
8249 + gdb_cat(&res, this->lvl3.result);
8250 + gdb_cat(&res, line);
8251 + xfree(this->lvl3.result);
8252 + this->lvl3.result = res;
8253 + break;
8255 + case OOB_COMPLETE:
8256 + this->frame_curlvl = -1;
8257 + if (this->lvl3.result != NULL
8258 + && (res = gdb_regexec(this->lvl3.result, PAT_INFO_FRAME, 1, NULL)) != NULL) {
8259 + this->frame_curlvl = atoi((char *)res);
8260 + xfree(res);
8263 + FREE(this->lvl3.result);
8264 + break;
8266 + return NULL;
8269 + # define SOURCE_FILENAME "\",file=\""
8270 + # define SOURCE_LINENUM "\",line=\""
8271 + /* Change frame highlight according to new frame level */
8272 + char *
8273 + gdb_stack_frame(this, state, line, obs)
8274 + gdb_T *this;
8275 + int state;
8276 + char_u *line;
8277 + struct obstack *obs;
8279 + char_u * res = NULL;
8280 + int rc = -1;
8281 + char tmp[32];
8282 + char_u * fname;
8283 + char_u * pnum;
8284 + char_u * quote;
8285 + char_u * ptr;
8286 + linenr_T lnum;
8288 + switch(state)
8290 + case OOB_CMD:
8291 + /* get info about frame_curlvl:
8292 + * ^done,stack=[frame={level="1",addr="0x080483bb",func="main",file="cltest_main.c",line="12"}] */
8293 + if (this->frame_curlvl >= 0) {
8294 + FREE(this->lvl3.result);
8296 + sprintf(tmp, "%d %d", this->frame_curlvl, this->frame_curlvl);
8297 + obstack_strcat(obs, "server interpreter-exec mi \"-stack-list-frames ");
8298 + obstack_strcat(obs, tmp);
8299 + obstack_strcat0(obs, "\"\n");
8300 + return (char *)obstack_finish(obs);
8302 + break;
8304 + case OOB_COLLECT:
8305 + gdb_cat(&res, this->lvl3.result);
8306 + gdb_cat(&res, line);
8307 + xfree(this->lvl3.result);
8308 + this->lvl3.result = res;
8309 + break;
8311 + case OOB_COMPLETE:
8312 + if (this->lvl3.result != NULL
8313 + && (ptr = STRSTR(this->lvl3.result, SOURCE_FILENAME)) != NULL
8314 + && (pnum = STRSTR(this->lvl3.result, SOURCE_LINENUM)) != NULL)
8316 + pnum += strlen(SOURCE_FILENAME);
8317 + lnum = atoi((char *)pnum);
8319 + ptr += strlen(SOURCE_FILENAME);
8321 + if ((quote = STRCHR(ptr, '"')) != NULL) {
8322 + fname = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
8324 + rc = 0;
8326 + /* set frame sign only if this is a new fname/lnum position */
8327 + if (this->frame_fname == NULL
8328 + || STRCMP(this->frame_fname, fname) != 0 || this->frame_lnum != lnum) {
8329 + FREE(this->frame_fname);
8330 + this->frame_fname = (char_u *)clewn_strsave((char *)fname);
8331 + this->frame_lnum = lnum;
8332 + rc = gdb_fr_set(this, fname, &lnum, obs);
8337 + if (rc != 0 && p_asm != 0)
8338 + this->pool.hilite = TRUE; /* do asm frame highliting */
8339 + FREE(this->lvl3.result);
8340 + break;
8342 + return NULL;
8344 + # endif /* GDB_LVL3_SUPPORT */
8346 + /* Get symbol file name */
8347 + char *
8348 + gdb_get_sfile(this, state, line, obs)
8349 + gdb_T *this;
8350 + int state;
8351 + char_u *line;
8352 + struct obstack *obs;
8354 + char_u *res = NULL;
8356 + switch(state)
8358 + case OOB_CMD:
8359 + return "server info target\n";
8361 + case OOB_COLLECT:
8362 + if (this->oob.cnt == 1
8363 + && (res = gdb_regexec(line, PAT_SFILE, 1, obs)) != NULL
8364 + && (this->sfile == NULL || STRCMP(res, this->sfile) != 0))
8366 + gdb_status(this, (char_u *)"new symbols", obs);
8367 + xfree(this->sfile);
8368 + this->sfile = (char_u *)clewn_strsave((char *)res);
8370 + break;
8372 + case OOB_COMPLETE:
8373 + if (this->oob.cnt == 0)
8375 + gdb_status(this, (char_u *)"empty target", obs);
8376 + FREE(this->sfile);
8378 + break;
8380 + return NULL;
8383 + /* Get GDB source directories */
8384 + char *
8385 + gdb_get_sourcedir(this, state, line, obs)
8386 + gdb_T *this;
8387 + int state;
8388 + char_u *line;
8389 + struct obstack *obs;
8391 + char_u *res = NULL;
8393 + if (obs) {} /* keep compiler happy */
8395 + switch(state)
8397 + case OOB_CMD:
8398 + FREE(this->lvl3.result);
8399 + return "server show directories\n";
8401 + case OOB_COLLECT:
8402 + gdb_cat(&res, this->lvl3.result);
8403 + gdb_cat(&res, line);
8404 + xfree(this->lvl3.result);
8405 + this->lvl3.result = res;
8406 + break;
8408 + case OOB_COMPLETE:
8409 + if (this->lvl3.result != NULL)
8411 + xfree(this->directories);
8412 + this->directories = gdb_regexec(this->lvl3.result, PAT_DIR, 1, NULL);
8413 + FREE(this->lvl3.result);
8415 + break;
8417 + return NULL;
8420 + #ifdef GDB_LVL3_SUPPORT
8421 + # ifndef FEAT_GDB
8422 + /* Source the project file */
8423 + char *
8424 + gdb_source_project(this, state, line, obs)
8425 + gdb_T *this;
8426 + int state;
8427 + char_u *line;
8428 + struct obstack *obs;
8430 + switch(state)
8432 + case OOB_CMD:
8433 + if (this->project_file != NULL
8434 + && cnb_state()
8435 + && this->project_state == PROJ_SOURCEIT)
8437 + this->project_state = PROJ_DONE;
8438 + fprintf(stderr, "source %s\n", this->project_file);
8440 + if (this->sfile != NULL)
8441 + fprintf(stderr, "Warning: symbol table \"%s\" was loaded before sourcing the project file\n", this->sfile);
8443 + obstack_strcat(obs, "server source ");
8444 + obstack_strcat(obs, this->project_file);
8445 + obstack_strcat0(obs, "\n");
8446 + return (char_u *)obstack_finish(obs);
8448 + break;
8450 + case OOB_COLLECT:
8451 + if (line != NULL)
8452 + fprintf(stderr, "%s\n", line);
8453 + break;
8455 + case OOB_COMPLETE:
8456 + /* force getting the source file list from gdb */
8457 + this->lvl3.get_source_list = TRUE;
8459 + /* this is required after 'restart' to display the gdb prompt */
8460 + fprintf(stderr, this->prompt);
8461 + break;
8464 + return NULL;
8467 + # define CWD_VALUE "^done,cwd=\""
8468 + /* Get current working directory */
8469 + char *
8470 + gdb_get_pwd(this, state, line, obs)
8471 + gdb_T *this;
8472 + int state;
8473 + char_u *line;
8474 + struct obstack *obs;
8476 + char_u * res = NULL;
8477 + char_u * ptr;
8478 + char_u * quote;
8480 + if (obs) {} /* keep compiler happy */
8482 + switch(state)
8484 + case OOB_CMD:
8485 + if (this->mode != GDB_MODE_LVL2) {
8486 + FREE(this->lvl3.result);
8487 + return "server interpreter-exec mi \"-environment-pwd\"\n";
8489 + break;
8491 + case OOB_COLLECT:
8492 + gdb_cat(&res, this->lvl3.result);
8493 + gdb_cat(&res, line);
8494 + xfree(this->lvl3.result);
8495 + this->lvl3.result = res;
8496 + break;
8498 + case OOB_COMPLETE:
8499 + if (this->lvl3.result != NULL
8500 + && (ptr = STRSTR(this->lvl3.result, CWD_VALUE)) != NULL
8501 + && (ptr += strlen(CWD_VALUE))
8502 + && (quote = (char_u *)strrchr(ptr, '"')) != NULL)
8504 + *quote = NUL;
8505 + gdb_cat(&res, (char_u *)"cd ");
8506 + gdb_cat(&res, ptr);
8507 + gdb_cat(&res, (char_u *)"\n");
8508 + xfree(this->pwd);
8509 + this->pwd = res;
8512 + FREE(this->lvl3.result);
8513 + break;
8515 + return NULL;
8518 + # define ARGS_VALUE "Argument list to give program being debugged when it is started is \""
8519 + /* Get args */
8520 + char *
8521 + gdb_get_args(this, state, line, obs)
8522 + gdb_T *this;
8523 + int state;
8524 + char_u *line;
8525 + struct obstack *obs;
8527 + char_u * res = NULL;
8528 + char_u * ptr;
8529 + char_u * quote;
8531 + if (obs) {} /* keep compiler happy */
8533 + switch(state)
8535 + case OOB_CMD:
8536 + FREE(this->lvl3.result);
8537 + return "server show args\n";
8539 + case OOB_COLLECT:
8540 + gdb_cat(&res, this->lvl3.result);
8541 + gdb_cat(&res, line);
8542 + xfree(this->lvl3.result);
8543 + this->lvl3.result = res;
8544 + break;
8546 + case OOB_COMPLETE:
8547 + if (this->lvl3.result != NULL
8548 + && (ptr = STRSTR(this->lvl3.result, ARGS_VALUE)) != NULL
8549 + && (ptr += strlen(ARGS_VALUE))
8550 + && (quote = (char_u *)strrchr(ptr, '"')) != NULL)
8552 + *quote = NUL;
8553 + gdb_cat(&res, "set args ");
8554 + gdb_cat(&res, ptr);
8555 + gdb_cat(&res, "\n");
8556 + xfree(this->args);
8557 + this->args = res;
8560 + FREE(this->lvl3.result);
8561 + break;
8563 + return NULL;
8565 + # endif
8567 + /* Get GDB current source file */
8568 + char *
8569 + gdb_source_cur(this, state, line, obs)
8570 + gdb_T *this;
8571 + int state;
8572 + char_u *line;
8573 + struct obstack *obs;
8575 + char_u *res = NULL;
8577 + if (obs) {} /* keep compiler happy */
8579 + switch(state)
8581 + case OOB_CMD:
8582 + FREE(this->lvl3.source_cur);
8583 + return "server interpreter-exec mi \"-file-list-exec-source-file\"\n";
8585 + case OOB_COLLECT:
8586 + gdb_cat(&res, this->lvl3.source_cur);
8587 + gdb_cat(&res, line);
8588 + xfree(this->lvl3.source_cur);
8589 + this->lvl3.source_cur = res;
8590 + break;
8592 + case OOB_COMPLETE:
8593 + break;
8595 + return NULL;
8598 + /* Get GDB current source file */
8599 + char *
8600 + gdb_source_list(this, state, line, obs)
8601 + gdb_T *this;
8602 + int state;
8603 + char_u *line;
8604 + struct obstack *obs;
8606 + char_u *res = NULL;
8608 + if (obs) {} /* keep compiler happy */
8610 + switch(state)
8612 + case OOB_CMD:
8613 + if (this->lvl3.get_source_list || this->lvl3.source_list == NULL) {
8614 + FREE(this->lvl3.source_list);
8615 + this->lvl3.get_source_list = FALSE;
8616 + return "server interpreter-exec mi \"-file-list-exec-source-files\"\n";
8618 + break;
8620 + case OOB_COLLECT:
8621 + gdb_cat(&res, this->lvl3.source_list);
8622 + gdb_cat(&res, line);
8623 + xfree(this->lvl3.source_list);
8624 + this->lvl3.source_list = res;
8625 + break;
8627 + case OOB_COMPLETE:
8628 + break;
8630 + return NULL;
8632 + #endif /* GDB_LVL3_SUPPORT */
8634 + # ifdef GDB_LVL3_SUPPORT
8635 + # define BKPT_RECORD "bkpt={number=\""
8636 + # define BKPT_ADDR "\",addr=\""
8637 + /*
8638 + * When a breakpoint is being set and asm option is on, get the
8639 + * instruction address of the last breakpoint, the one being set.
8640 + * This address is used in get_asm() to disassemble the function
8641 + * containing this address.
8642 + */
8643 + static char *
8644 + get_lastbp(this, state, line, obs)
8645 + gdb_T *this;
8646 + int state;
8647 + char_u *line;
8648 + struct obstack *obs;
8650 + char_u *res = NULL;
8651 + int found = FALSE;
8652 + char_u *record = NULL;
8653 + char_u *ptr;
8654 + char_u *addr;
8655 + bpinfo_T *p;
8656 + int bp_num;
8658 + if (obs) {} /* keep compiler happy */
8660 + switch (state)
8662 + case OOB_CMD:
8663 + /* GDB sends sometimes ANO_BP_INVALID when stepping, even
8664 + * though no breakpoints have been changed.
8665 + * Avoid checking for last bp in this case, because this
8666 + * may cause hiliting a bp in a new buffer when what is
8667 + * expected is a new frame */
8668 + if (this->bp_state & BPS_FR_INVALID)
8669 + return NULL;
8671 + /* A breakpoint is being set in assembly */
8672 + if (p_asm != 0 && (this->bp_state & BPS_INVALID)
8673 + && (this->bp_state & BPS_BP_SET))
8675 + this->bp_state &= ~BPS_BP_SET;
8676 + FREE(this->lvl3.result);
8678 + /* fetch GDB bp table info */
8679 + return "server interpreter-exec mi -break-list\n";
8681 + break;
8683 + case OOB_COLLECT:
8684 + gdb_cat(&res, this->lvl3.result);
8685 + gdb_cat(&res, line);
8686 + xfree(this->lvl3.result);
8687 + this->lvl3.result = res;
8688 + break;
8690 + case OOB_COMPLETE:
8691 + if ((ptr = this->lvl3.result) != NULL)
8693 + /* search for last record in breakpoint table */
8694 + do
8696 + if ((ptr = STRSTR(ptr, BKPT_RECORD)) != NULL)
8698 + record = ptr;
8699 + ptr++;
8702 + while (ptr != NULL);
8704 + /* last record */
8705 + if (record != NULL
8706 + && (bp_num = atoi((char *)(record + strlen(BKPT_RECORD)))) > 0)
8708 + /* look it up in bpinfo list */
8709 + for (p = this->bpinfo; p != NULL; p = p->next)
8711 + if (bp_num == p->id)
8713 + found = TRUE;
8714 + break;
8718 + /* not found: set asm_add so that get_asm will
8719 + * do the disassembling */
8720 + if (! found && (addr = STRSTR(record, BKPT_ADDR)) != NULL)
8722 + xfree(this->asm_add);
8723 + this->asm_add =
8724 + gdb_regexec(addr + strlen(BKPT_ADDR), PAT_ADD, 1, NULL);
8728 + FREE(this->lvl3.result);
8730 + break;
8732 + return NULL;
8734 + # endif /* GDB_LVL3_SUPPORT */
8736 + /* Get the function name corresponding to asm_add */
8737 + char *
8738 + gdb_get_asmfunc(this, state, line, obs)
8739 + gdb_T *this;
8740 + int state;
8741 + char_u *line;
8742 + struct obstack *obs;
8744 + switch(state)
8746 + case OOB_CMD:
8747 + if (this->asm_add != NULL)
8749 + obstack_strcat(obs, "server info symbol 0x");
8750 + obstack_strcat(obs, this->asm_add);
8751 + obstack_strcat0(obs, "\n");
8752 + return (char *)obstack_finish(obs);
8754 + FREE(this->asm_func);
8755 + break;
8757 + case OOB_COLLECT:
8758 + xfree(this->asm_func);
8759 + this->asm_func = gdb_regexec(line, PAT_ASM_FUNC, 1, NULL);
8760 + break;
8762 + return NULL;
8765 + /*
8766 + * This function is a hack to fix errors occuring in GDB command
8767 + * "info symbol ADDR" that sometimes cannot find the symbol corresponding to
8768 + * a given ADDR, when GDB command "print/a ADDR" can.
8769 + * "print/a ADDR" is used as a last resort because it changes the value history.
8770 + * "output/a ADDR" does not change the value history, but the output of this
8771 + * command misses a newline.
8772 + */
8773 + char *
8774 + gdb_get_asmfunc_hack(this, state, line, obs)
8775 + gdb_T *this;
8776 + int state;
8777 + char_u *line;
8778 + struct obstack *obs;
8780 + switch(state)
8782 + case OOB_CMD:
8783 + if (this->asm_add != NULL && this->asm_func == NULL)
8785 + obstack_strcat(obs, "server print/a 0x");
8786 + obstack_strcat(obs, this->asm_add);
8787 + obstack_strcat0(obs, "\n");
8788 + return (char *)obstack_finish(obs);
8790 + break;
8792 + case OOB_COLLECT:
8793 + xfree(this->asm_func);
8794 + this->asm_func = gdb_regexec(line, PAT_ASM_FUNC_P, 1, NULL);
8795 + break;
8797 + return NULL;
8800 + # define ASM_ABORTED "DISASSEMBLY ABORTED"
8802 + /*
8803 + * Disassemble new function containing asm_add and highlight asm_add
8804 + * if this->pool.hilite is TRUE
8805 + */
8806 + char *
8807 + gdb_get_asm(this, state, line, obs)
8808 + gdb_T *this;
8809 + int state;
8810 + char_u *line;
8811 + struct obstack *obs;
8812 + # ifdef FEAT_GDB
8814 + buf_T *buf = this->pool.buf[this->pool.idx];
8815 + buf_T *oldbuf = curbuf;
8816 + char_u *res = NULL;
8817 + int oldest = 0;
8818 + int age = 0;
8819 + linenr_T lnum;
8820 + win_T *win;
8821 + int i;
8823 + if (p_asm == 0)
8825 + FREE(this->asm_add);
8826 + return NULL;
8829 + lnum = (buf != NULL ? BUFLASTL(buf) : 0);
8831 + switch (state)
8833 + case OOB_CMD:
8834 + if (this->asm_add != NULL && !gdb_as_frset(this, obs))
8836 + /* pickup least recent buffer */
8837 + for (i = this->pool.max; i > 0; )
8839 + i--;
8840 + if (this->pool.age[i] >= age && this->pool.buf[i] != NULL)
8842 + age = this->pool.age[i];
8843 + oldest = i;
8847 + /* no buffers in pool */
8848 + if ((buf = this->pool.buf[oldest]) == NULL)
8850 + this->pool.hilite = FALSE;
8851 + FREE(this->asm_add);
8852 + return NULL;
8854 + this->pool.idx = oldest;
8856 + /* clear the buffer */
8857 + gdb_clear_asmbuf(this, buf);
8859 + /* init msg_busy */
8860 + obstack_strcat(obs, "Disassembling 0x");
8861 + obstack_strcat0(obs, this->asm_add);
8862 + res = (char_u *)obstack_finish(obs);
8863 + gdb_msg_busy(res);
8865 + /* send cmd */
8866 + obstack_strcat(obs, "server disassemble 0x");
8867 + obstack_strcat(obs, this->asm_add);
8868 + obstack_strcat0(obs, "\n");
8869 + return (char *)obstack_finish(obs);
8871 + this->pool.hilite = FALSE;
8872 + break;
8874 + case OOB_COLLECT:
8875 + if (buf == NULL)
8876 + return NULL;
8877 + curbuf = buf;
8879 + /* concatenate with line after an annotation
8880 + * and replace line, otherwise add */
8881 + if (this->line != NULL && this->annoted)
8883 + obstack_strcat(obs, this->line);
8884 + obstack_strcat0(obs, line);
8885 + line = (char_u *)obstack_finish(obs);
8886 + ml_delete(lnum--, FALSE);
8889 + /* first line: remove empty line after the inserted one */
8890 + if (ml_append(lnum, line, 0, 0) == OK && lnum == 0)
8891 + ml_delete(buf->b_ml.ml_line_count, FALSE);
8892 + curbuf = oldbuf;
8894 + if ((this->oob.cnt % 1000) == 0)
8895 + gdb_msg_busy(NULL);
8897 + xfree(this->line);
8898 + this->line = (char_u *)clewn_strsave((char *)line);
8899 + break;
8901 + case OOB_COMPLETE:
8902 + if (buf == NULL)
8903 + return NULL;
8904 + curbuf = buf;
8906 + if (this->oob.state & OS_INTR)
8908 + if (lnum >= 1 && STRCMP(ASM_ABORTED, ml_get(1)) != 0)
8910 + /* Clear buffer when interrupted */
8911 + while (lnum-- > 0)
8912 + ml_delete(buf->b_ml.ml_line_count, FALSE);
8914 + ml_append(0, (char_u *)ASM_ABORTED, 0, 0);
8915 + lnum = buf->b_ml.ml_line_count;
8916 + changed_lines(1, 0, lnum, lnum);
8917 + curbuf = oldbuf;
8919 + this->pool.age[this->pool.idx] = ASM_OLD;
8920 + gdb_edit_file(this, buf, NULL, 1, obs);
8923 + /* write the prompt */
8924 + gdb_write_buf(this, this->line, TRUE);
8925 + gdb_redraw(buf);
8927 + else
8929 + changed_lines(1, 0, lnum, lnum);
8931 + /* set buffer name to function name */
8932 + if (this->asm_func != NULL)
8934 + obstack_strcat(obs, this->asm_func);
8935 + obstack_strcat0(obs, "-asm");
8936 + res = (char_u *)obstack_finish(obs);
8937 + gdb_as_setname(res);
8939 + curbuf = oldbuf;
8941 + /* highlite $asm_add and update window if displayed */
8942 + if (! gdb_as_frset(this, obs) && (win = gdb_btowin(buf)) != NULL)
8944 + gdb_set_cursor(win, 1);
8945 + redraw_win_later(win, NOT_VALID);
8949 + msg_clr_cmdline();
8950 + FREE(this->asm_add);
8951 + this->pool.hilite = FALSE;
8952 + break;
8954 + return NULL;
8956 + # else
8958 + char_u *res = NULL;
8959 + char_u *fname;
8961 + if (p_asm == 0)
8963 + FREE(this->asm_add);
8964 + return NULL;
8967 + switch (state)
8969 + case OOB_CMD:
8970 + if (this->asm_add != NULL && ! gdb_as_frset(this, obs))
8972 + FREE(this->pool.name);
8974 + /* get a unique file name for this disassembled function
8975 + * and open the file for creation
8976 + * the file name suffix is '.clasm' so that it can be set
8977 + * to 'autoread' by the runtime file clewn.vim */
8978 + if (this->asm_func != NULL) {
8979 + obstack_strcat(obs, this->asm_func);
8980 + obstack_strcat0(obs, ".clasm");
8981 + fname = (char_u *)obstack_finish(obs);
8983 + if (this->asm_func == NULL || (this->pool.fd = clewn_opentmpfile(fname,
8984 + &(this->pool.name), 1)) == NULL)
8986 + this->pool.hilite = FALSE;
8987 + return NULL;
8989 + this->pool.line_offset = 0L;
8991 + /* create the buffer */
8992 + if ((this->pool.buf = cnb_create_buf(this->pool.name)) == -1)
8994 + this->pool.hilite = FALSE;
8996 + fclose(this->pool.fd);
8997 + this->pool.fd = NULL;
8998 + if (this->pool.name != NULL)
8999 + (void)unlink(this->pool.name);
9000 + FREE(this->pool.name);
9001 + return NULL;
9004 + /* init msg_busy */
9005 + obstack_strcat(obs, "Disassembling 0x");
9006 + obstack_strcat0(obs, this->asm_add);
9007 + res = (char_u *)obstack_finish(obs);
9008 + gdb_msg_busy(res);
9010 + /* send cmd */
9011 + this->lastline = 0;
9012 + obstack_strcat(obs, "server disassemble 0x");
9013 + obstack_strcat(obs, this->asm_add);
9014 + obstack_strcat0(obs, "\n");
9015 + return (char_u *)obstack_finish(obs);
9017 + this->pool.hilite = FALSE;
9018 + break;
9020 + case OOB_COLLECT:
9021 + if (this->pool.fd == NULL)
9022 + goto fail;
9024 + /* ignore when interrupted */
9025 + if (this->oob.state & OS_INTR)
9026 + return NULL;
9028 + /* concatenate with line after an annotation
9029 + * and replace line, otherwise add */
9030 + if (this->line != NULL && this->annoted)
9032 + obstack_strcat(obs, this->line);
9033 + obstack_strcat0(obs, line);
9034 + line = (char_u *)obstack_finish(obs);
9036 + this->lastline--;
9037 + if (fseek(this->pool.fd, this->pool.line_offset, SEEK_SET) != 0)
9038 + goto fail;
9041 + /* write a newline except at first line */
9042 + if (this->lastline != 0)
9044 + if ((this->pool.line_offset = ftell(this->pool.fd)) == -1
9045 + || fputs("\n", this->pool.fd) < 0)
9046 + goto fail;
9048 + this->lastline++;
9050 + /* write the line */
9051 + if (fputs(line, this->pool.fd) < 0)
9052 + goto fail;
9054 + if ((this->oob.cnt % 400) == 0)
9055 + gdb_msg_busy(NULL);
9057 + xfree(this->line);
9058 + this->line = (char_u *)clewn_strsave((char *)line);
9059 + break;
9061 + case OOB_COMPLETE:
9062 + if (this->pool.fd == NULL)
9063 + goto fail;
9065 + if (this->oob.state & OS_INTR)
9067 + FREE(this->asm_add);
9068 + this->pool.hilite = FALSE;
9069 + goto fail;
9071 + else
9073 + /* highlite $asm_add */
9074 + (void)gdb_as_frset(this, obs);
9076 + /* write last new line */
9077 + if (fputs("\n", this->pool.fd) < 0)
9078 + goto fail;
9080 + /* clear the line */
9081 + gdb_msg_busy("FIN");
9083 + /* set the buffer as an asm buffer */
9084 + cnb_set_asm(this->pool.buf);
9087 + FREE(this->asm_add);
9089 + this->pool.buf = -1;
9090 + fclose(this->pool.fd);
9091 + this->pool.fd = NULL;
9092 + FREE(this->pool.name);
9093 + this->pool.hilite = FALSE;
9094 + break;
9096 + return NULL;
9097 + fail:
9098 + /* clear the line */
9099 + gdb_msg_busy("FIN");
9101 + cnb_kill(this->pool.buf);
9102 + this->pool.buf = -1;
9104 + if (this->pool.fd != NULL)
9105 + fclose(this->pool.fd);
9106 + this->pool.fd = NULL;
9108 + if (this->pool.name != NULL)
9109 + (void)unlink(this->pool.name);
9110 + FREE(this->pool.name);
9111 + return NULL;
9113 + # endif /* FEAT_GDB */
9115 + # ifdef GDB_LVL3_SUPPORT
9116 + /*
9117 + * Get the breakpoints info record table.
9118 + */
9119 + static char *
9120 + get_bp(this, state, line, obs)
9121 + gdb_T *this;
9122 + int state;
9123 + char_u *line;
9124 + struct obstack *obs;
9126 + char_u *res = NULL;
9127 + char_u *record = NULL;
9128 + char_u *ptr;
9129 + bpinfo_T *p;
9131 + switch (state)
9133 + case OOB_CMD:
9134 + /* gdb 6.4 does not provide anymore the right annotations for breakpoints
9135 + * when in level 3 (note that they are still there when setting annotate
9136 + * level 2, I thought level 2 was deprecated, what a zoo !), so we look
9137 + * for new or changed breakpoints systematically now */
9138 + if (this->mode == GDB_MODE_LVL3)
9139 + this->bp_state = BPS_INVALID;
9141 + /* When an ANO_BP_INVALID annotation has been received,
9142 + * or when we are stepping (more accurately: got a new frame):
9143 + * fetch bp table */
9144 + if (this->bp_state & BPS_INVALID || this->bp_state & BPS_FR_INVALID)
9146 + FREE(this->lvl3.result);
9147 + this->bufIsChanged = FALSE;
9149 + /* handle case where an error occured last time */
9150 + FREE(this->record);
9151 + gdb_free_bplist(&(this->tmplist));
9153 + /* fetch GDB bp table info */
9154 + return "server interpreter-exec mi -break-list\n";
9157 + this->bp_state &= ~BPS_INVALID;
9158 + this->bp_state &= ~BPS_FR_INVALID;
9159 + this->bp_state &= ~BPS_BP_HIT;
9160 + break;
9162 + case OOB_COLLECT:
9163 + gdb_cat(&res, this->lvl3.result);
9164 + gdb_cat(&res, line);
9165 + xfree(this->lvl3.result);
9166 + this->lvl3.result = res;
9167 + break;
9169 + case OOB_COMPLETE:
9170 + if ((ptr = this->lvl3.result) != NULL)
9172 + /* process all records except last */
9173 + do
9175 + if ((ptr = STRSTR(ptr, BKPT_RECORD)) != NULL
9176 + && ptr > this->lvl3.result)
9178 + *(ptr - 1) = NUL;
9179 + if (record != NULL)
9180 + process_record(this, record, obs);
9182 + record = ptr;
9183 + ptr++;
9186 + while (ptr != NULL);
9188 + /* process last record */
9189 + if (record != NULL)
9190 + process_record(this, record, obs);
9192 + FREE(this->record);
9194 + /* All records left in the old table are breakpoints that have
9195 + * been deleted: delete the corresponding highliting sign */
9196 + for (p = this->bpinfo; p != NULL; p = p->next)
9197 + gdb_unlite(BP_SIGN_ID(p->id));
9199 + this->bp_state &= ~BPS_INVALID;
9200 + this->bp_state &= ~BPS_FR_INVALID;
9201 + this->bp_state &= ~BPS_BP_HIT;
9203 + /* replace with new table */
9204 + gdb_free_bplist(&(this->bpinfo));
9205 + this->bpinfo = this->tmplist;
9206 + this->tmplist = NULL;
9208 + FREE(this->lvl3.result);
9210 + break;
9212 + return NULL;
9215 + # define BKPT_ENABLED "\",enabled=\""
9216 + # define BKPT_DISP "\",disp=\""
9217 + # define BKPT_SCRIPT "\",script={"
9218 + # define BKPT_TYPE "\",type=\"breakpoint\""
9219 + # define BKPT_LINE "\",line=\""
9220 + # define BKPT_SOURCE "\",file=\""
9221 + # define BKPT_AT "\",at=\"<"
9222 + /* Process the current info record */
9223 + static void
9224 + process_record(this, record, obs)
9225 + gdb_T *this;
9226 + char_u *record;
9227 + struct obstack *obs;
9229 + char_u *bp_add = NULL;
9230 + char_u *bp_line = NULL;
9231 + char_u *bp_source = NULL;
9232 + char_u *bp_at = NULL;
9233 + char_u *ptr;
9234 + char_u *end;
9235 + char_u *quote;
9236 + char_u *plus;
9238 + /* allocate a new record or reuse an existing one
9239 + * and initialize its fields */
9240 + if (this->record == NULL)
9241 + this->record = (bpinfo_T *)xcalloc(sizeof(bpinfo_T));
9243 + this->record->id = -1;
9244 + this->record->enabled = TRUE;
9245 + # ifdef BP_INVALID_ANO_MISSING
9246 + this->record->disposition = TRUE;
9247 + # endif
9248 + this->record->cont = FALSE;
9249 + # ifdef FEAT_GDB
9250 + this->record->buf = NULL;
9251 + # else
9252 + this->record->buf = -1;
9253 + this->record->typenr_en = -1;
9254 + this->record->typenr_dis = -1;
9255 + # endif
9256 + this->record->lnum = 0;
9257 + this->record->next = NULL;
9259 + /* breakpoint number */
9260 + this->record->id = atoi((char *)(record + strlen(BKPT_RECORD)));
9262 + /* enabled state */
9263 + if ((ptr = STRSTR(record, BKPT_ENABLED)) != NULL
9264 + && *(ptr + strlen(BKPT_ENABLED)) == 'n')
9265 + this->record->enabled = FALSE;
9267 + # ifdef BP_INVALID_ANO_MISSING
9268 + /* disposition */
9269 + if ((ptr = STRSTR(record, BKPT_DISP)) != NULL
9270 + && STRSTR(ptr + strlen(BKPT_DISP), "keep") == NULL)
9271 + this->record->disposition = FALSE;
9272 + # endif
9274 + /* parse script for 'continue' as last statement */
9275 + if ((ptr = STRSTR(record, BKPT_SCRIPT)) != NULL)
9277 + ptr += strlen(BKPT_SCRIPT);
9278 + if ((end = STRCHR(ptr, '}')) != NULL)
9280 + while ((ptr = STRCHR(ptr, '"')) != NULL && ptr < end)
9282 + ptr++;
9283 + if (gdb_regexec(ptr, PAT_BP_CONT, 1, obs) != NULL
9284 + || gdb_regexec(ptr, PAT_BP_CONT, 2, obs) != NULL)
9286 + this->record->cont = TRUE; /* continue */
9287 + break;
9293 + /* sanity check and discard watchpoints and others */
9294 + if (this->record->id <= 0 || STRSTR(record, BKPT_TYPE) == NULL)
9295 + return;
9297 + /* address */
9298 + if ((ptr = STRSTR(record, BKPT_ADDR)) != NULL)
9299 + bp_add = gdb_regexec(ptr + strlen(BKPT_ADDR), PAT_ADD, 1, obs);
9301 + /* line */
9302 + if ((ptr = STRSTR(record, BKPT_LINE)) != NULL)
9304 + ptr += strlen(BKPT_LINE);
9305 + if ((quote = STRCHR(ptr, '"')) != NULL)
9306 + bp_line = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
9309 + /* source */
9310 + if ((ptr = STRSTR(record, BKPT_SOURCE)) != NULL)
9312 + ptr += strlen(BKPT_SOURCE);
9313 + if ((quote = STRCHR(ptr, '"')) != NULL)
9314 + bp_source = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
9317 + /* at */
9318 + if ((ptr = STRSTR(record, BKPT_AT)) != NULL)
9320 + ptr += strlen(BKPT_AT);
9321 + if ((quote = STRCHR(ptr, '>')) != NULL)
9323 + if ((plus = STRCHR(ptr, '+')) != NULL && plus < quote)
9324 + bp_at = (char_u *)obstack_copy0(obs, ptr, (plus - ptr));
9325 + else
9326 + bp_at = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
9330 + gdb_process_record(this, bp_add, bp_at, bp_line, bp_source, obs);
9333 + /* Update the variables objects and the variables window */
9334 + static char *
9335 + varobj_update(this, state, line, obs)
9336 + gdb_T *this;
9337 + int state;
9338 + char_u *line;
9339 + struct obstack *obs;
9341 + # ifdef FEAT_GDB
9342 + char_u *ptrn;
9343 + # else
9344 + static char *result = NULL; /* mark the start and end of object operations */
9345 + # endif
9346 + char_u *res = NULL;
9347 + varobj_T *obj;
9349 + switch (state)
9351 + case OOB_CMD:
9352 + if (this->lvl3.varitem == NULL)
9354 + /* start with first in list */
9355 + this->lvl3.varitem = this->lvl3.varlist;
9356 + this->lvl3.varnext_cmd = VCMD_INIT;
9358 + oob_cmd:
9359 + /* next OOB_CMD */
9360 + if ((obj = this->lvl3.varitem) != NULL)
9362 + FREE(this->lvl3.result);
9364 + /* create a new object and give it a name */
9365 + if (this->lvl3.varnext_cmd == VCMD_INIT && obj->name == NULL)
9367 + if (
9368 + # ifdef FEAT_GDB
9369 + this->var_buf != NULL
9370 + # else
9371 + this->var_buf > 0
9372 + # endif
9375 + if (obj->format != NULL)
9376 + this->lvl3.varnext_cmd = VCMD_FORMAT;
9377 + else
9378 + this->lvl3.varnext_cmd = VCMD_PRINT;
9380 + this->lvl3.varcmd = VCMD_CREATE;
9382 + obstack_strcat(obs, "server interpreter-exec mi \"-var-create - * (");
9383 + obstack_strcat(obs, obj->expression);
9384 + obstack_strcat0(obs, ")\"\n");
9385 + return (char *)obstack_finish(obs);
9387 + else
9389 + /* remove silently from list */
9390 + remove_object(this, obj);
9391 + goto oob_cmd;
9395 + /* sanity check: an object must have a name
9396 + * this should never occur */
9397 + if (obj->name == NULL)
9399 + /* silently ignore this error */
9400 + this->lvl3.varnext_cmd = VCMD_INIT;
9401 + this->lvl3.varitem = obj->next;
9402 + goto oob_cmd;
9405 + /* search for the object in the variables window
9406 + * if it does not exist, then -var-delete it */
9407 + if (this->lvl3.varnext_cmd == VCMD_INIT)
9409 + # ifdef FEAT_GDB
9410 + pos_T pos;
9412 + pos.lnum = 1;
9413 + pos.col = 0;
9415 + obstack_strcat(obs, "^\\s*");
9416 + obstack_strcat(obs, obj->name);
9417 + obstack_strcat0(obs, ":");
9418 + ptrn = (char_u *)obstack_finish(obs);
9420 + if (this->var_buf == NULL
9421 + || (this->var_buf->b_ml.ml_flags & ML_EMPTY)
9422 + || (searchit(NULL, this->var_buf, &pos,
9423 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) == FAIL))
9424 + # else
9425 + int lnum;
9427 + if (this->var_buf <= 0 || cnb_search_obj(obj->name, &lnum) == NULL)
9428 + # endif
9430 + /* not in gdb variables window, delete it */
9431 + this->lvl3.varcmd = VCMD_DELETE;
9433 + obstack_strcat(obs, "server interpreter-exec mi \"-var-delete var");
9434 + obstack_strcat(obs, obj->name);
9435 + obstack_strcat0(obs, "\"\n");
9436 + return (char *)obstack_finish(obs);
9440 + /* list children if any (need to run this cmd before update) */
9441 + if (this->lvl3.varnext_cmd == VCMD_INIT)
9443 + this->lvl3.varnext_cmd = VCMD_UPDATE;
9445 + if (obj->children)
9447 + this->lvl3.varcmd = VCMD_CHILDREN;
9449 + obstack_strcat(obs, "server interpreter-exec mi \"-var-list-children var");
9450 + obstack_strcat(obs, obj->name);
9451 + obstack_strcat0(obs, "\"\n");
9452 + return (char *)obstack_finish(obs);
9456 + /* set the format */
9457 + if (this->lvl3.varnext_cmd == VCMD_FORMAT)
9459 + if (obj->format != NULL && STRLEN(obj->format) == 2)
9461 + obstack_strcat(obs, "server interpreter-exec mi \"-var-set-format var");
9462 + obstack_strcat(obs, obj->name);
9464 + switch(*(obj->format + 1))
9466 + case 't':
9467 + obstack_strcat0(obs, " binary\"\n");
9468 + break;
9469 + case 'd':
9470 + obstack_strcat0(obs, " decimal\"\n");
9471 + break;
9472 + case 'x':
9473 + obstack_strcat0(obs, " hexadecimal\"\n");
9474 + break;
9475 + case 'o':
9476 + obstack_strcat0(obs, " octal\"\n");
9477 + break;
9478 + default:
9479 + obstack_strcat0(obs, " natural\"\n");
9480 + break;
9483 + this->lvl3.varnext_cmd = VCMD_PRINT;
9484 + this->lvl3.varcmd = VCMD_FORMAT;
9486 + return (char *)obstack_finish(obs);
9488 + else
9490 + this->lvl3.varnext_cmd = VCMD_INIT;
9491 + this->lvl3.varitem = obj->next;
9492 + goto oob_cmd;
9496 + /* update object */
9497 + if (this->lvl3.varnext_cmd == VCMD_UPDATE)
9499 + this->lvl3.varnext_cmd = VCMD_PRINT;
9500 + this->lvl3.varcmd = VCMD_UPDATE;
9502 + obstack_strcat(obs, "server interpreter-exec mi \"-var-update var");
9503 + obstack_strcat(obs, obj->name);
9504 + obstack_strcat0(obs, "\"\n");
9505 + return (char *)obstack_finish(obs);
9508 + /* print */
9509 + if (this->lvl3.varnext_cmd == VCMD_PRINT)
9511 + obj->state &= ~VS_ERROR;
9512 + this->lvl3.varcmd = VCMD_PRINT;
9514 + obstack_strcat(obs, "server output ");
9515 + obstack_strcat(obs, obj->format);
9516 + obstack_strcat(obs, " ");
9517 + obstack_strcat(obs, obj->expression);
9518 + obstack_strcat0(obs, "\n");
9519 + return (char *)obstack_finish(obs);
9522 + /* evaluate object expression */
9523 + if (this->lvl3.varnext_cmd == VCMD_EVALUATE)
9525 + this->lvl3.varcmd = VCMD_EVALUATE;
9527 + obstack_strcat(obs, "server interpreter-exec mi \"-var-evaluate-expression var");
9528 + obstack_strcat(obs, obj->name);
9529 + obstack_strcat0(obs, "\"\n");
9530 + return (char *)obstack_finish(obs);
9533 + break;
9535 + case OOB_COLLECT:
9536 + gdb_cat(&res, this->lvl3.result);
9537 + gdb_cat(&res, line);
9538 + xfree(this->lvl3.result);
9539 + this->lvl3.result = res;
9540 + break;
9542 + case OOB_COMPLETE:
9543 + # ifdef FEAT_GDB
9544 + return varobj_complete(this, obs);
9545 + # else
9546 + /* start of object operations */
9547 + if (result == NULL && this->var_buf > 0)
9548 + cnb_startAtomic(this->var_buf);
9550 + result = varobj_complete(this, obs);
9552 + /* end of object operations */
9553 + if (result == NULL && this->var_buf > 0)
9554 + cnb_endAtomic(this->var_buf);
9556 + return result;
9557 + # endif
9560 + return NULL;
9563 + # define VOBJ_NAME "^done,name=\"var"
9564 + # define VOBJ_CHILD "\",numchild=\""
9565 + # define VOBJ_SCOPE "\",in_scope=\""
9566 + # define VOBJ_VALUE "^done,value=\""
9567 + /*
9568 + * Process the OOB_COMPLETE part of varobj_update()
9569 + * Return anything not NULL except when last object in varlist
9570 + * and after the last varcmd which may be: a failed VCMD_CREATE,
9571 + * VCMD_DELETE, highlighted VCMD_UPDATE, VCMD_PRINT, VCMD_EVALUATE
9572 + */
9573 + static char *
9574 + varobj_complete(this, obs)
9575 + gdb_T *this;
9576 + struct obstack *obs;
9578 + char_u *displine; /* the new display item line */
9579 + char_u *res;
9580 + # ifdef FEAT_GDB
9581 + buf_T *oldbuf = curbuf;
9582 + linenr_T lnum;
9583 + win_T *win;
9584 + # endif
9585 + varobj_T *obj;
9586 + char_u *ptr;
9587 + char_u *last;
9588 + char_u *child;
9589 + char_u *quote;
9591 + if ((obj = this->lvl3.varitem) != NULL)
9593 + switch (this->lvl3.varcmd)
9595 + case VCMD_CREATE:
9596 + /* result of object creation */
9597 + if (this->lvl3.result != NULL
9598 + && (ptr = STRSTR(this->lvl3.result, VOBJ_NAME)) != NULL
9599 + && (ptr += strlen(VOBJ_NAME))
9600 + && (quote = STRCHR(ptr, '"')) != NULL
9601 + && (child = STRSTR(this->lvl3.result, VOBJ_CHILD)) != NULL)
9603 + obj->name = (char_u *)clewn_strnsave((char *)ptr, (quote - ptr));
9604 + obj->children = (atoi((char *)(child + strlen(VOBJ_CHILD))) > 0);
9606 + FREE(this->lvl3.result);
9607 + return (char *)obj; /* next command */
9609 + else
9611 + EMSG(_("Unable to create variable object"));
9612 + remove_object(this, obj);
9613 + FREE(this->lvl3.result);
9614 + this->lvl3.varnext_cmd = VCMD_INIT;
9615 + return (char *)this->lvl3.varitem; /* next object */
9617 + break;
9619 + case VCMD_DELETE:
9620 + remove_object(this, obj);
9621 + FREE(this->lvl3.result);
9622 + this->lvl3.varnext_cmd = VCMD_INIT;
9623 + return (char *)this->lvl3.varitem; /* next object */
9625 + case VCMD_CHILDREN:
9626 + FREE(this->lvl3.result);
9627 + return (char *)obj; /* next command */
9629 + case VCMD_FORMAT:
9630 + FREE(this->lvl3.result);
9631 + return (char *)obj; /* next command */
9633 + case VCMD_UPDATE:
9634 + if (this->lvl3.result != NULL
9635 + &&(ptr = STRSTR(this->lvl3.result, VOBJ_SCOPE)) != NULL)
9637 + ptr += strlen(VOBJ_SCOPE);
9638 + if ((STRSTR(ptr, "false")) == ptr)
9640 + /* set "out of scope" highlighting (={-}) */
9641 + varobj_hilite(this, obj, (int)'-', obs);
9642 + goto nextobj;
9644 + else
9646 + /* object needs updating */
9647 + FREE(this->lvl3.result);
9648 + return (char *)obj; /* next command */
9651 + else
9653 + /* turn off highlighting */
9654 + varobj_hilite(this, obj, (int)'=', obs);
9655 + goto nextobj;
9657 + break;
9659 + case VCMD_PRINT:
9660 + /* fall back to GDB/MI when unable to print expression
9661 + * because it's not the right frame */
9662 + if (obj->state & VS_ERROR)
9664 + obj->state &= ~VS_ERROR;
9665 + this->lvl3.varnext_cmd = VCMD_EVALUATE;
9666 + FREE(this->lvl3.result);
9667 + return (char *)obj; /* next command */
9670 + /* build the display line including ={*}, the hiliting sign */
9671 + obstack_strcat(obs, obj->name);
9672 + obstack_strcat(obs, ":");
9673 + obstack_strcat(obs, obj->format);
9674 + obstack_strcat(obs, " ");
9675 + obstack_strcat(obs, obj->expression);
9676 + obstack_strcat(obs, " ={*} ");
9677 + if (this->lvl3.result != NULL) {
9678 + obstack_strcat0(obs, this->lvl3.result);
9680 + displine = (char_u *)obstack_finish(obs);
9682 + /* add the newly created object to variables window */
9683 + if (obj->state & VS_INIT)
9685 + # ifdef FEAT_GDB
9686 + if (this->var_buf != NULL)
9688 + lnum = BUFLASTL(this->var_buf);
9690 + /* edit variables buffer in available window */
9691 + if (gdb_edit_file(this, this->var_buf, NULL, lnum, obs) != NULL)
9693 + /* add to variables buffer */
9694 + if (ml_append(lnum, displine, 0, 0) == OK)
9696 + /* first line ever: remove empty line after the
9697 + * one just inserted */
9698 + if (lnum == 0)
9699 + ml_delete(this->var_buf->b_ml.ml_line_count, FALSE);
9701 + changed_lines(this->var_buf->b_ml.ml_line_count - 1,
9702 + 0, this->var_buf->b_ml.ml_line_count, 1);
9705 + /* update top line */
9706 + curwin->w_cursor.lnum = this->var_buf->b_ml.ml_line_count;
9707 + update_topline();
9709 + /* status line changed */
9710 + curwin->w_redr_status = TRUE;
9712 + /* move back to previous window if still there */
9713 + if ((win = gdb_btowin(oldbuf)) != NULL)
9714 + win_goto(win);
9716 + obj->state &= ~VS_INIT;
9718 + # else
9719 + if (this->var_buf > 0)
9721 + cnb_append(this->var_buf, displine, obs);
9722 + obj->state &= ~VS_INIT;
9724 + # endif
9727 + /* update and highlight object value */
9728 + else
9729 + varobj_replace(this, obj, displine, obs);
9731 + goto nextobj;
9733 + case VCMD_EVALUATE:
9734 + if (this->lvl3.result != NULL
9735 + && (ptr = STRSTR(this->lvl3.result, VOBJ_VALUE)) != NULL
9736 + && (ptr += strlen(VOBJ_VALUE))
9737 + && (quote = (char_u *)strrchr((char *)ptr, '"')) != NULL)
9739 + res = (char_u *)obstack_copy0(obs, ptr, (quote - ptr));
9741 + /* remove all `\' in `\"' */
9742 + for (ptr = last = res; *ptr; ptr++)
9744 + if (*ptr != '\\' || *(ptr + 1) != '"')
9745 + *last++ = *ptr;
9747 + *last = NUL;
9749 + /* build the display line including ={*}, the hiliting sign */
9750 + obstack_strcat(obs, obj->name);
9751 + obstack_strcat(obs, ":");
9752 + obstack_strcat(obs, obj->format);
9753 + obstack_strcat(obs, " ");
9754 + obstack_strcat(obs, obj->expression);
9755 + obstack_strcat(obs, " ={*} ");
9756 + obstack_strcat0(obs, res);
9757 + displine = (char_u *)obstack_finish(obs);
9760 + /* update and highlight object value */
9761 + varobj_replace(this, obj, displine, obs);
9764 + goto nextobj;
9768 + return NULL;
9769 + nextobj:
9770 + FREE(this->lvl3.result);
9771 + this->lvl3.varitem = obj->next;
9772 + this->lvl3.varnext_cmd = VCMD_INIT;
9774 + /* When not at the end of varlist, return a non null object
9775 + * to get gdb_oob_send() to call again varobj_update() for
9776 + * the next object */
9777 + return (char *)this->lvl3.varitem;
9780 + # define OBHI_CHANGED " ={*} "
9781 + # define OBHI_UNCHANGED " ={=} "
9782 + # define OBHI_DESCOPED " ={-} "
9783 + /* Change object highlighting to type */
9784 + static void
9785 + varobj_hilite(this, obj, type, obs)
9786 + gdb_T *this;
9787 + varobj_T *obj;
9788 + int type; /* hiliting type, may be '*', '=' or '-' */
9789 + struct obstack *obs;
9790 + # ifdef FEAT_GDB
9792 + buf_T *oldbuf = curbuf;
9793 + char_u *ptrn;
9794 + char_u *line;
9795 + char_u *oldline;
9796 + char_u *ptr;
9797 + pos_T pos;
9798 + win_T *win;
9800 + pos.lnum = 1;
9801 + pos.col = 0;
9803 + /* search for obj in variables window */
9804 + obstack_strcat(obs, "^\\s*");
9805 + obstack_strcat(obs, obj->name);
9806 + obstack_strcat0(obs, ":");
9807 + ptrn = (char_u *)obstack_finish(obs);
9809 + if (this->var_buf != NULL && obj != NULL && obj->name != NULL
9810 + && ! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
9811 + && searchit(NULL, this->var_buf, &pos,
9812 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
9814 + line = ml_get_buf(this->var_buf, pos.lnum, FALSE);
9815 + oldline = obstack_strsave(obs, line);
9817 + if ((type == '-' && ((ptr = STRSTR(oldline, OBHI_CHANGED)) != NULL
9818 + || (ptr = STRSTR(oldline, OBHI_UNCHANGED)) != NULL))
9819 + || (type == '*' && ((ptr = STRSTR(oldline, OBHI_UNCHANGED)) != NULL
9820 + || (ptr = STRSTR(oldline, OBHI_DESCOPED)) != NULL))
9821 + || (type == '=' && ((ptr = STRSTR(oldline, OBHI_DESCOPED)) != NULL
9822 + || (ptr = STRSTR(oldline, OBHI_CHANGED)) != NULL)))
9824 + *(ptr + 3) = type;
9826 + /* replace line */
9827 + curbuf = this->var_buf;
9828 + ml_replace(pos.lnum, oldline, TRUE);
9829 + changed_lines(pos.lnum, 0, pos.lnum + 1, 0);
9830 + curbuf = oldbuf;
9832 + if ((win = gdb_btowin(this->var_buf)) != NULL)
9833 + redraw_win_later(win, NOT_VALID);
9837 + # else
9839 + char_u *oldline;
9840 + char_u *line;
9841 + char_u *ptr;
9842 + int lnum;
9844 + /* search for obj in variables buffer */
9845 + if (this->var_buf > 0 && obj != NULL && obj->name != NULL
9846 + && (oldline = cnb_search_obj(obj->name, &lnum)) != NULL)
9848 + line = obstack_strsave(obs, oldline);
9850 + if ((type == '-' && ((ptr = STRSTR(line, OBHI_CHANGED)) != NULL
9851 + || (ptr = STRSTR(line, OBHI_UNCHANGED)) != NULL))
9852 + || (type == '*' && ((ptr = STRSTR(line, OBHI_UNCHANGED)) != NULL
9853 + || (ptr = STRSTR(line, OBHI_DESCOPED)) != NULL))
9854 + || (type == '=' && ((ptr = STRSTR(line, OBHI_DESCOPED)) != NULL
9855 + || (ptr = STRSTR(line, OBHI_CHANGED)) != NULL)))
9857 + *(ptr + 3) = type;
9859 + /* replace line */
9860 + cnb_replace(this->var_buf, line, lnum, obs);
9864 + # endif
9866 + /* Replace object line in variables buffer with line */
9867 + static void
9868 + varobj_replace(this, obj, line, obs)
9869 + gdb_T *this;
9870 + varobj_T *obj;
9871 + char_u *line;
9872 + struct obstack *obs;
9873 + # ifdef FEAT_GDB
9875 + buf_T *oldbuf = curbuf;
9876 + win_T *oldwin = curwin;
9877 + char_u *ptrn;
9878 + linenr_T lnum;
9879 + win_T *win;
9880 + pos_T pos;
9882 + pos.lnum = 1;
9883 + pos.col = 0;
9885 + /* search for object in variables window */
9886 + obstack_strcat(obs, "^\\s*");
9887 + obstack_strcat(obs, obj->name);
9888 + obstack_strcat0(obs, ":");
9889 + ptrn = (char_u *)obstack_finish(obs);
9891 + if (this->var_buf != NULL && obj != NULL && obj->name != NULL
9892 + && ! (this->var_buf->b_ml.ml_flags & ML_EMPTY)
9893 + && searchit(NULL, this->var_buf, &pos,
9894 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
9896 + lnum = pos.lnum;
9898 + /* replace line */
9899 + curbuf = this->var_buf;
9900 + ml_replace(lnum, line, TRUE);
9901 + changed_lines(lnum, 0, lnum + 1, 0);
9903 + if ((win = gdb_btowin(this->var_buf)) != NULL)
9905 + win->w_cursor.lnum = lnum;
9907 + curwin = win;
9908 + check_cursor();
9909 + update_topline();
9910 + curwin = oldwin;
9912 + win->w_redr_status = TRUE;
9914 + redraw_win_later(win, NOT_VALID);
9916 + curbuf = oldbuf;
9919 + # else
9921 + int lnum;
9923 + /* search for object in variables buffer */
9924 + if (this->var_buf > 0 && obj != NULL && obj->name != NULL
9925 + && cnb_search_obj(obj->name, &lnum) != NULL)
9926 + cnb_replace(this->var_buf, line, lnum, obs);
9928 + # endif
9930 + /* Remove varobj item from valist */
9931 + static void
9932 + remove_object(this, item)
9933 + gdb_T *this;
9934 + varobj_T *item;
9936 + varobj_T **pt;
9937 + varobj_T *next;
9939 + for (pt = &(this->lvl3.varlist); *pt != NULL; pt = &((*pt)->next))
9940 + if (*pt == item)
9942 + next = (*pt)->next;
9943 + this->lvl3.varitem = next;
9945 + xfree(item->name);
9946 + xfree(item->format);
9947 + xfree(item->expression);
9948 + xfree(item);
9949 + *pt = next;
9950 + return;
9953 + # endif /* GDB_LVL3_SUPPORT */
9955 + /*
9956 + * Add a breakpoint record to the head of the tmp list and highlite
9957 + * the corresponding sign if the record refers to a loaded buffer
9958 + * or to an editable file, and in this case load it.
9959 + */
9960 + void
9961 + gdb_process_record(this, address, at, line, source, obs)
9962 + gdb_T *this;
9963 + char_u *address; /* breakpoint address */
9964 + char_u *at; /* breakpoint function */
9965 + char_u *line; /* breakpoint line in source */
9966 + char_u *source; /* breakpoint source file name */
9967 + struct obstack *obs;
9968 + # ifdef FEAT_GDB
9970 + win_T *oldwin = curwin;
9971 + bpinfo_T *record = this->record;
9972 + char_u *bp_file = NULL;
9973 + buf_T *buf = NULL;
9974 + char_u *ptrn;
9975 + bpinfo_T *p, **pt;
9976 + pos_T pos;
9977 + int i;
9978 + int lnum;
9980 + /*
9981 + * Look for this breakpoint in previous list
9982 + */
9983 + for (pt = &(this->bpinfo); *pt != NULL; pt = &((*pt)->next))
9985 + p = *pt;
9987 + /* The breakpoint number exists in the old table:
9988 + * update the highliting sign and do not even parse
9989 + * the line (assume the file and line of a breakpoint
9990 + * are immutable)
9991 + * move the old record to tmplist and update its sign
9992 + */
9993 + if (record->id == p->id)
9995 + /* update enabled */
9996 + if (record->enabled != p->enabled)
9998 + p->enabled = record->enabled;
9999 + if ((p->typenr = gdb_define_sign(p->id, p->enabled)) != -1)
10001 + buf_addsign(p->buf, BP_SIGN_ID(p->id), p->lnum, p->typenr);
10002 + update_debug_sign(p->buf, p->lnum);
10006 + # ifdef BP_INVALID_ANO_MISSING
10007 + /* update disposition */
10008 + p->disposition = record->disposition;
10009 + # endif
10011 + /* update 'continue' */
10012 + p->cont = record->cont;
10014 + /* move from old list to new list */
10015 + *pt = p->next; /* unlink from old list */
10016 + p->next = this->tmplist; /* link to head of new table */
10017 + this->tmplist = p;
10018 + return; /* record may be reused */
10022 + /*
10023 + * A new breakpoint number: edit the file if possible
10024 + */
10025 + /* An asm breakpoint */
10026 + if (address != NULL && at != NULL)
10028 + bp_file = obstack_strsave(obs, at);
10030 + /* Search all buffers in the asm buffer pool whose name starts
10031 + * with bp_file and find the one containing a line starting
10032 + * with address */
10033 + obstack_strcat(obs, "^\\s*0x0*");
10034 + obstack_strcat0(obs, address);
10035 + ptrn = (char_u *)obstack_finish(obs);
10037 + for (i = 0; i < this->pool.max; i++)
10039 + pos.lnum = 1;
10040 + pos.col = 0;
10042 + if (this->pool.buf[i] != NULL
10043 + && STRSTR(this->pool.buf[i]->b_fname, bp_file) != NULL
10044 + && !(this->pool.buf[i]->b_ml.ml_flags & ML_EMPTY)
10045 + && searchit(NULL, this->pool.buf[i], &pos,
10046 + FORWARD, ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
10048 + this->pool.age[i] = 0;
10049 + record->lnum = pos.lnum;
10050 + buf = this->pool.buf[i];
10051 + break;
10055 + bp_file = NULL;
10058 + /* A plain breakpoint */
10059 + else if (line != NULL && (record->lnum = atoi((char *)line)) > 0
10060 + && source != NULL)
10062 + bp_file = obstack_strsave(obs, source);
10065 + /*
10066 + * Edit the file or asm buffer
10067 + * when the table is reported by GDB as having changed
10068 + * or when this buffer is the frame buffer and the frame
10069 + * is invalid (because: we might be setting a frame in
10070 + * a newly disassembled buffer and must set again all
10071 + * its breakpoints)
10072 + */
10073 + if ((bp_file != NULL || buf != NULL)
10074 + && (this->bp_state & BPS_INVALID
10075 + || (p_asm != 0
10076 + && buf != NULL
10077 + && buf == this->fr_buf
10078 + && (this->bp_state & BPS_FR_INVALID)))
10081 + /* bufIsChanged is TRUE when previous gdb_edit_file() failed because
10082 + * the user cancelled the operation after having been warned the
10083 + * buffer is changed. In this case, do not try to gdb_edit_file()
10084 + * again for the next new breakpoints
10085 + * (as the operation is cancelled). */
10086 + if (! this->bufIsChanged)
10088 + if (gdb_edit_file(this, buf, bp_file, record->lnum, obs) != NULL)
10090 + /* MUST redraw the screen before calling update_debug_sign():
10091 + * update_debug_sign() invokes win_update()
10092 + * the screen might have been scrolled when Vim ask the
10093 + * user to confirm changes made to the previous buffer */
10094 + gdb_redraw(curwin->w_buffer);
10096 + record->buf = curwin->w_buffer;
10098 + if ((record->typenr =
10099 + gdb_define_sign(record->id, record->enabled)) != -1)
10101 + /* add bp sign */
10102 + buf_addsign(record->buf, BP_SIGN_ID(record->id),
10103 + record->lnum, record->typenr);
10104 + update_debug_sign(record->buf, record->lnum);
10106 + /* Set the frame sign again in case this is
10107 + * a newly disassembled buffer */
10108 + if (this->frame_pc != NULL
10109 + && p_asm != 0
10110 + && this->fr_buf == NULL
10111 + && ! (record->buf->b_ml.ml_flags & ML_EMPTY))
10113 + pos.lnum = 1;
10114 + pos.col = 0;
10116 + obstack_strcat(obs, "^\\s*0x0*");
10117 + obstack_strcat0(obs, this->frame_pc);
10118 + ptrn = (char_u *)obstack_finish(obs);
10120 + if (ptrn != NULL
10121 + && searchit(NULL, record->buf, &pos, FORWARD,
10122 + ptrn, 1L, SEARCH_KEEP, RE_LAST, (linenr_T)0, NULL) != FAIL)
10124 + gdb_fr_lite(this, record->buf, pos.lnum, obs);
10128 + /* Handle the case where bps are set after the frame sign:
10129 + * new disassembled code or reediting a wiped-out plain
10130 + * buffer or stepping in a newly disassembled buffer */
10131 + if (record->buf == this->fr_buf
10132 + && (this->bp_state & BPS_BP_HIT
10133 + || (p_asm != 0
10134 + && (this->bp_state & BPS_FR_INVALID)))
10135 + && (lnum =
10136 + buf_findsign(this->fr_buf, FRAME_SIGN)) != 0)
10138 + /* remove frame sign and add it again on top
10139 + * of this new breakpoint */
10140 + if (lnum == record->lnum)
10141 + gdb_fr_lite(this, this->fr_buf, lnum, obs);
10143 + /* move back cursor to frame */
10144 + gdb_set_cursor(gdb_btowin(this->fr_buf), lnum);
10148 + record->next = this->tmplist; /* link to head of new table */
10149 + this->tmplist = record;
10150 + this->record = NULL; /* forget record */
10152 + else
10154 + this->bufIsChanged = bufIsChanged(curbuf);
10155 + win_goto(oldwin);
10160 + return;
10162 + # else
10164 + bpinfo_T *record = this->record;
10165 + char_u *bp_file = NULL;
10166 + int buf = -1;
10167 + bpinfo_T *p, **pt;
10168 + char_u *fname;
10169 + linenr_T lnum;
10170 + int bufno;
10172 + /*
10173 + * Look for this breakpoint in previous list
10174 + */
10175 + for (pt = &(this->bpinfo); *pt != NULL; pt = &((*pt)->next))
10177 + p = *pt;
10179 + /* The breakpoint number exists in the old table:
10180 + * remove old sign and replace by new one
10181 + * move the old record to tmplist and update its sign
10182 + */
10183 + if (record->id == p->id)
10185 + /* update enabled */
10186 + if (record->enabled != p->enabled)
10188 + p->enabled = record->enabled;
10189 + if ((p->typenr = gdb_define_bpsign(p, obs)) != -1)
10191 + cnb_buf_delsign(p->buf, BP_SIGN_ID(p->id));
10192 + cnb_buf_addsign(p->buf, BP_SIGN_ID(p->id), p->typenr, p->lnum, obs);
10196 + # ifdef BP_INVALID_ANO_MISSING
10197 + /* update disposition */
10198 + p->disposition = record->disposition;
10199 + # endif
10201 + /* update 'continue' */
10202 + p->cont = record->cont;
10204 + /* move from old list to new list */
10205 + *pt = p->next; /* unlink from old list */
10206 + p->next = this->tmplist; /* link to head of new table */
10207 + this->tmplist = p;
10208 + return; /* record may be reused */
10212 + /*
10213 + * A new breakpoint number: edit the file if possible
10214 + */
10215 + /* An asm breakpoint */
10216 + if (address != NULL && at != NULL)
10218 + bp_file = obstack_strsave(obs, at);
10220 + /* Search all buffers in the asm buffer pool whose name starts
10221 + * with bp_file and find the one containing a line starting
10222 + * with address */
10223 + for (bufno = 1; ! cnb_outofbounds(bufno); bufno++)
10225 + if ((fname = cnb_filename(bufno)) != NULL
10226 + && STRSTR(fname, bp_file) != NULL
10227 + && (lnum = searchfor(fname, address)) > 0)
10229 + record->lnum = lnum;
10230 + buf = bufno;
10231 + break;
10235 + bp_file = NULL;
10238 + /* A plain breakpoint */
10239 + else if (line != NULL && (record->lnum = atoi((char *)line)) > 0
10240 + && source != NULL)
10242 + bp_file = obstack_strsave(obs, source);
10245 + /*
10246 + * Edit the file or asm buffer
10247 + * when the table is reported by GDB as having changed
10248 + * or when this buffer is the frame buffer and the frame
10249 + * is invalid (because: we might be setting a frame in
10250 + * a newly disassembled buffer and must set again all
10251 + * its breakpoints)
10252 + */
10253 + if ((bp_file != NULL || cnb_isvalid_buffer(buf))
10254 + && (this->bp_state & BPS_INVALID
10255 + || (p_asm != 0
10256 + && cnb_isvalid_buffer(buf)
10257 + && buf == this->fr_buf
10258 + && (this->bp_state & BPS_FR_INVALID)))
10261 + if ((record->buf = gdb_edit_file(buf, bp_file, record->lnum, 1, obs)) > 0)
10263 + if ((record->typenr = gdb_define_bpsign(record, obs)) != -1)
10265 + /* add bp sign */
10266 + cnb_buf_addsign(record->buf, BP_SIGN_ID(record->id),
10267 + record->typenr, record->lnum, obs);
10269 + /* Set the frame sign again in case this is
10270 + * a newly disassembled buffer */
10271 + if (this->frame_pc != NULL
10272 + && p_asm != 0
10273 + && ! cnb_isvalid_buffer(this->fr_buf)
10274 + && (fname = cnb_filename(record->buf)) != NULL
10275 + && (lnum = searchfor(fname, this->frame_pc)) > 0)
10277 + gdb_fr_lite(this, record->buf, lnum, obs);
10280 + /* Handle the case where bps are set after the frame sign:
10281 + * new disassembled code or reediting a wiped-out plain
10282 + * buffer or stepping in a newly disassembled buffer */
10283 + if (record->buf == this->fr_buf
10284 + && (this->bp_state & BPS_BP_HIT
10285 + || (p_asm != 0
10286 + && (this->bp_state & BPS_FR_INVALID)))
10287 + && (lnum = find_fr_sign(this->fr_buf)) != 0)
10289 + /* remove frame sign and add it again on top
10290 + * of this new breakpoint */
10291 + if (lnum == record->lnum)
10292 + gdb_fr_lite(this, this->fr_buf, lnum, obs);
10296 + record->next = this->tmplist; /* link to head of new table */
10297 + this->tmplist = record;
10298 + this->record = NULL; /* forget record */
10302 + return;
10304 + # endif /* FEAT_GDB */
10306 + /*
10307 + * Parse str for annotation, set this->note.
10308 + * Return byte address following annotation, NULL if none found.
10309 + * Return byte address following ^Z^Z when unknown annotation.
10310 + */
10311 + static char_u *
10312 + parse_note(this, str)
10313 + gdb_T *this;
10314 + char_u *str; /* string to parse */
10316 + char_u *note = NULL;
10317 + annotation_T *pt;
10318 + int len;
10320 + if (str != NULL && (note = STRSTR(str, "\032\032")) != NULL)
10322 + this->note = ANO_ANY;
10323 + note += 2;
10325 + for (pt = annotations; pt->str != NULL; pt++)
10327 + len = STRLEN(pt->str);
10329 + if (STRSTR(note, pt->str) == note
10330 + && (*(note + len) == NUL || isspace(*(note + len))))
10332 + this->note = pt->id;
10333 + return note + strlen((char *)pt->str);
10337 + return note;
10340 + # ifndef FEAT_GDB
10341 + /* Return annotation type of 'str' or ANO_NONE when not found. */
10342 + static int
10343 + get_note(this, str)
10344 + gdb_T *this;
10345 + char_u *str; /* string to parse */
10347 + int oldnote = this->note;
10348 + int note = ANO_NONE;
10350 + if (IS_ANNOTATION(str) && parse_note(this, str) != NULL)
10351 + note = this->note;
10353 + this->note = oldnote;
10354 + return note;
10356 + # endif /* FEAT_GDB */
10357 + # endif /* defined(GDB_LVL2_SUPPORT) || defined(GDB_LVL3_SUPPORT) */
10358 + #endif /* defined(FEAT_GDB) || defined(HAVE_CLEWN) */
10359 diff -c --new-file old/clewn/misc.c src/clewn/misc.c
10360 *** old/clewn/misc.c 1970-01-01 01:00:00.000000000 +0100
10361 --- src/clewn/misc.c 2008-10-11 16:29:18.000000000 +0200
10362 ***************
10363 *** 0 ****
10364 --- 1,645 ----
10365 + /* vi:set ts=8 sts=4 sw=4:
10367 + * Copyright (C) 2004 Xavier de Gaye.
10369 + * This program is free software; you can redistribute it and/or modify
10370 + * it under the terms of the GNU General Public License as published by
10371 + * the Free Software Foundation; either version 2, or (at your option)
10372 + * any later version.
10374 + * This program is distributed in the hope that it will be useful,
10375 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10376 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10377 + * GNU General Public License for more details.
10379 + * You should have received a copy of the GNU General Public License
10380 + * along with this program (see the file COPYING); if not, write to the
10381 + * Free Software Foundation, Inc.,
10382 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
10384 + * $Id: misc.c 217 2008-10-11 14:29:18Z xavier $
10385 + */
10387 + #ifdef HAVE_CLEWN
10388 + # include <config.h>
10389 + #else
10390 + # include <auto/config.h>
10391 + void vim_beep ();
10392 + #endif
10394 + #include <stdio.h>
10395 + #include <string.h>
10396 + #include <errno.h>
10397 + #include <ctype.h>
10398 + #include <sys/stat.h>
10400 + #ifdef HAVE_READLINE_READLINE_H
10401 + # include <readline/readline.h>
10402 + #endif
10404 + #ifdef HAVE_STDLIB_H
10405 + # include <stdlib.h>
10406 + #endif
10407 + #ifndef EXIT_FAILURE
10408 + # define EXIT_FAILURE 1
10409 + #endif
10411 + #ifdef HAVE_UNISTD_H
10412 + # include <unistd.h>
10413 + #endif
10415 + #ifdef HAVE_FCNTL_H
10416 + # include <fcntl.h>
10417 + #endif
10419 + #if !defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME)
10420 + # include <time.h> /* on some systems time.h should not be
10421 + included together with sys/time.h */
10422 + #endif
10423 + #ifdef HAVE_SYS_TIME_H
10424 + # include <sys/time.h>
10425 + #endif
10427 + #ifndef HAVE_SELECT
10428 + # ifdef HAVE_SYS_POLL_H
10429 + # include <sys/poll.h>
10430 + # else
10431 + # ifdef HAVE_POLL_H
10432 + # include <poll.h>
10433 + # endif
10434 + # endif
10435 + #endif
10437 + /* Note: Some systems need both string.h and strings.h (Savage). However,
10438 + * some systems can't handle both, only use string.h in that case. */
10439 + #if defined(HAVE_STRINGS_H) && !defined(NO_STRINGS_WITH_STRING_H)
10440 + # include <strings.h>
10441 + #endif
10443 + #include "obstack.h"
10444 + #ifdef FEAT_GDB
10445 + # include "vim.h"
10446 + #else
10447 + # include "clewn.h"
10448 + #endif
10450 + /* do not define xmalloc and family */
10451 + #undef GDB_MTRACE
10452 + #include "gdb.h"
10454 + #include "misc.h"
10456 + #if defined(__CYGWIN__) || defined(__CYGWIN32__)
10457 + # define WIN32UNIX /* Compiling for Win32 using Unix files. */
10458 + # define BINARY_FILE_IO
10459 + # undef HAVE_FCHDIR /* doesn't work well in most versions */
10460 + #endif
10462 + #if defined(HAVE_GETCWD) && defined(HAVE_GETWD)
10463 + # define USE_GETCWD
10464 + #endif
10466 + /* boolean constants */
10467 + #define FALSE 0
10468 + #define TRUE 1
10470 + /*
10471 + * EMX doesn't have a global way of making open() use binary I/O.
10472 + * Use O_BINARY for all open() calls.
10473 + */
10474 + #if defined(__EMX__) || defined(__CYGWIN32__)
10475 + # define O_EXTRA O_BINARY
10476 + #else
10477 + # define O_EXTRA 0
10478 + #endif
10480 + static void (*misc_abort)(void) = NULL; /* registered abort function */
10482 + /* Register an abort function for when allocating memory fails. */
10483 + void
10484 + xatabort(abort_func)
10485 + void (*abort_func)(void);
10487 + misc_abort = abort_func;
10490 + /* allocate memory */
10491 + void *
10492 + xmalloc(size)
10493 + size_t size;
10495 + void *value = malloc(size);
10497 + if (value == 0)
10499 + #ifdef HAVE_CLEWN
10500 + rl_cleanup_after_signal(); /* have readline reset terminal */
10501 + fprintf(stderr, "\nvirtual memory exhausted\n");
10502 + #endif
10503 + if (misc_abort != NULL)
10504 + misc_abort();
10505 + else
10506 + exit(EXIT_FAILURE);
10508 + return value;
10511 + /* Allocate memory and set all bytes to zero */
10512 + void *
10513 + xcalloc(size)
10514 + size_t size;
10516 + void *p = xmalloc(size);
10517 + clewn_memset(p, 0, size);
10518 + return p;
10521 + /* Changes the size of the memory block pointed to by ptr to size bytes. */
10522 + void *
10523 + xrealloc(ptr, size)
10524 + void *ptr;
10525 + size_t size;
10527 + void *value = realloc(ptr, size);
10529 + if (value == 0)
10531 + #ifdef HAVE_CLEWN
10532 + rl_cleanup_after_signal(); /* have readline reset terminal */
10533 + fprintf(stderr, "\nvirtual memory exhausted\n");
10534 + #endif
10535 + if (misc_abort != NULL)
10536 + misc_abort();
10537 + else
10538 + exit(EXIT_FAILURE);
10540 + return value;
10543 + /* Replacement for free() that ignores NULL pointers. */
10544 + void
10545 + xfree(x)
10546 + void *x;
10548 + if (x != NULL)
10549 + free(x);
10552 + #ifndef HAVE_MEMSET
10553 + void *
10554 + clewn_memset(ptr, c, size)
10555 + void *ptr;
10556 + int c;
10557 + size_t size;
10559 + char *p = ptr;
10561 + while (size-- > 0)
10562 + *p++ = c;
10563 + return ptr;
10565 + #endif
10567 + #ifdef CLEWN_MEMMOVE
10568 + /*
10569 + * Version of memmove() that handles overlapping source and destination.
10570 + * For systems that don't have a function that is guaranteed to do that (SYSV).
10571 + */
10572 + void
10573 + clewn_memmove(d, s, len)
10574 + void *d;
10575 + void *s;
10576 + size_t len;
10578 + /* a void doesn't have a size, we use char pointers */
10579 + char *dst = d;
10580 + char *src = s;
10582 + /* overlap, copy backwards */
10583 + if (dst > src && dst < src + len)
10585 + src += len;
10586 + dst += len;
10587 + while (len-- > 0)
10588 + *--dst = *--src;
10590 + else /* copy forwards */
10591 + while (len-- > 0)
10592 + *dst++ = *src++;
10594 + #endif
10596 + /* copy a string into newly allocated memory */
10597 + char *
10598 + clewn_strsave(string)
10599 + char *string;
10601 + char *p;
10602 + size_t len;
10604 + if (string != NULL) {
10605 + len = strlen(string) + 1;
10606 + p = xmalloc(len);
10607 + clewn_memmove(p, string, len);
10609 + else {
10610 + p = xmalloc(1);
10611 + *p = '\0';
10613 + return p;
10616 + char *
10617 + clewn_strnsave(string, len)
10618 + char *string;
10619 + size_t len;
10621 + char *p = xmalloc(len + 1);
10623 + *p = '\0';
10624 + if (string != NULL)
10625 + strncpy(p, string, len);
10626 + *(p + len) = '\0';
10627 + return p;
10630 + void
10631 + clewn_sleep(msec)
10632 + int msec;
10634 + /*
10635 + * Everybody sleeps in a different way...
10636 + * Prefer nanosleep(), some versions of usleep() can only sleep up to
10637 + * one second.
10638 + */
10639 + #ifdef HAVE_NANOSLEEP
10641 + struct timespec ts;
10643 + ts.tv_sec = msec / 1000;
10644 + ts.tv_nsec = (msec % 1000) * 1000000;
10645 + (void)nanosleep(&ts, NULL);
10647 + #else
10648 + # ifdef HAVE_USLEEP
10649 + while (msec >= 1000)
10651 + usleep((999 * 1000));
10652 + msec -= 999;
10654 + usleep((msec * 1000));
10655 + # else
10656 + # ifndef HAVE_SELECT
10657 + poll(NULL, 0, msec);
10658 + # else
10659 + # ifdef __EMX__
10660 + _sleep2(msec);
10661 + # else
10663 + struct timeval tv;
10665 + tv.tv_sec = msec / 1000;
10666 + tv.tv_usec = (msec % 1000) * 1000;
10667 + /*
10668 + * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
10669 + * a patch from Sun to fix this. Reported by Gunnar Pedersen.
10670 + */
10671 + select(0, NULL, NULL, NULL, &tv);
10673 + # endif /* __EMX__ */
10674 + # endif /* HAVE_SELECT */
10675 + # endif /* HAVE_NANOSLEEP */
10676 + #endif /* HAVE_USLEEP */
10679 + /* Give a warning for an error. */
10680 + void
10681 + clewn_beep()
10683 + #ifdef HAVE_CLEWN
10684 + /* use readline utility */
10685 + # ifdef HAVE_RL_DING
10686 + rl_ding();
10687 + # else
10688 + ding(); /* deprecated */
10689 + # endif
10690 + #else
10691 + vim_beep();
10692 + #endif
10695 + /*
10696 + * Get name of current directory into buffer 'buf' of length 'len' bytes.
10697 + * Return 1 for success, 0 for failure.
10698 + */
10699 + int
10700 + clewn_getwd(buf, len)
10701 + char *buf;
10702 + int len;
10704 + #if defined(USE_GETCWD)
10705 + if (getcwd(buf, len) == NULL)
10707 + strcpy(buf, strerror(errno));
10708 + return 0;
10710 + return 1;
10711 + #else
10712 + return (getwd(buf) != NULL ? 1 : 0);
10713 + #endif
10716 + /*
10717 + * Get absolute file name into buffer 'buf' of length 'len' bytes.
10718 + * return 0 for failure, 1 for success
10719 + */
10720 + int
10721 + clewn_fullpath(fname, buf, len, force)
10722 + char *fname;
10723 + char *buf;
10724 + int len;
10725 + int force; /* also expand when already absolute path */
10727 + int l;
10728 + #ifdef HAVE_FCHDIR
10729 + int fd = -1;
10730 + static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
10731 + #endif
10732 + char olddir[MAXPATHL];
10733 + char *p;
10734 + int retval = 1;
10736 + *buf = '\0';
10737 + if (fname == NULL)
10738 + return 0;
10740 + /* expand it if forced or not an absolute path */
10741 + if (force || *fname != '/')
10743 + /*
10744 + * If the file name has a path, change to that directory for a moment,
10745 + * and then do the getwd() (and get back to where we were).
10746 + * This will get the correct path name with "../" things.
10747 + */
10748 + if ((p = strrchr(fname, '/')) != NULL)
10750 + #ifdef HAVE_FCHDIR
10751 + /*
10752 + * Use fchdir() if possible, it's said to be faster and more
10753 + * reliable. But on SunOS 4 it might not work. Check this by
10754 + * doing a fchdir() right now.
10755 + */
10756 + if (!dont_fchdir)
10758 + fd = open(".", O_RDONLY | O_EXTRA, 0);
10759 + if (fd >= 0 && fchdir(fd) < 0)
10761 + close(fd);
10762 + fd = -1;
10763 + dont_fchdir = TRUE; /* don't try again */
10766 + #endif
10768 + /* Only change directory when we are sure we can return to where
10769 + * we are now. After doing "su" chdir(".") might not work. */
10770 + if (
10771 + #ifdef HAVE_FCHDIR
10772 + fd < 0 &&
10773 + #endif
10774 + (clewn_getwd(olddir, MAXPATHL) == 0
10775 + || chdir((char *)olddir) != 0))
10777 + p = NULL; /* can't get current dir: don't chdir */
10778 + retval = 0;
10780 + else
10782 + /* The directory is copied into buf[], to be able to remove
10783 + * the file name without changing it (could be a string in
10784 + * read-only memory) */
10785 + if (p - fname >= len)
10786 + retval = 0;
10787 + else
10789 + strncpy(buf, fname, p - fname);
10790 + buf[p - fname] = '\0';
10791 + if (chdir((char *)buf))
10792 + retval = 0;
10793 + else
10794 + fname = p + 1;
10795 + *buf = '\0';
10800 + if (clewn_getwd(buf, len) == 0)
10802 + retval = 0;
10803 + *buf = '\0';
10806 + if (p != NULL)
10808 + #ifdef HAVE_FCHDIR
10809 + if (fd >= 0)
10811 + (void)fchdir(fd);
10812 + close(fd);
10814 + else
10815 + #endif
10816 + (void)chdir((char *)olddir);
10819 + l = strlen(buf);
10820 + if (l >= len)
10821 + retval = 0;
10822 + else
10824 + if (l > 0 && buf[l - 1] != '/' && *fname != '\0')
10825 + strcat(buf, "/");
10829 + /* catch file names which are too long */
10830 + if (retval == 0 || ((int)(strlen(buf) + strlen(fname)) >= len))
10831 + return 0;
10833 + strcat(buf, fname);
10835 + return 1;
10838 + /*
10839 + * Get a full path name for the file named 'name'.
10840 + * If name is an absolute path, just stat it. Otherwise, add name to
10841 + * each directory in GDB source directories and stat the result.
10842 + */
10843 + char *
10844 + get_fullpath(name, sourcedir, source_cur, source_list, obs)
10845 + char *name; /* file name */
10846 + char *sourcedir; /* GDB source directories */
10847 + char *source_cur; /* GDB current source */
10848 + char *source_list; /* GDB source list */
10849 + struct obstack *obs;
10851 + char *pathname;
10852 + char pathbuf[MAXPATHL];
10853 + struct stat st;
10854 + char *dir;
10855 + char *ptr;
10856 + char *last;
10857 + char *hay;
10858 + char *found;
10859 + char *end;
10861 + if (name == NULL || *name == NUL)
10862 + return NULL;
10864 + /* an absolute path name */
10865 + if (*name == '/')
10867 + if (stat((char *)name, &st) == 0)
10868 + return name;
10869 + else
10870 + /* strip off the directory part and continue */
10871 + name = strrchr(name, '/') + 1;
10874 + if (sourcedir == NULL) /* use current working directory */
10875 + sourcedir = GDB_CWD;
10877 + /* proceed with each directory in GDB source directories */
10878 + ptr = sourcedir;
10879 + do
10881 + if ((last = strchr(ptr, ':')) != NULL)
10882 + *last++ = NUL;
10884 + if (strcmp(ptr, GDB_CDIR) == 0) /* compilation directory */
10886 + /* hay: file="NAME",fullname=" */
10887 + obstack_strcat(obs, "file=\"");
10888 + obstack_strcat(obs, name);
10889 + obstack_strcat0(obs, "\",fullname=\"");
10890 + hay = (char *)obstack_finish(obs);
10892 + /* name is the current sourcefile: use gdb compilation directory */
10893 + if (source_cur != NULL && (found=strstr(source_cur, hay)) != NULL ){
10894 + found += strlen(hay);
10895 + if ((end=strstr(found, "\"")) != NULL)
10896 + return (char *)obstack_copy0(obs, found, end - found);
10899 + /* lookup for first occurence of name in source list */
10900 + if (source_list != NULL && (found=strstr(source_list, hay)) != NULL ){
10901 + found += strlen(hay);
10902 + if ((end=strstr(found, "\"")) != NULL)
10903 + return (char *)obstack_copy0(obs, found, end - found);
10906 + dir = NULL;
10908 + else if (strcmp(ptr, GDB_CWD) == 0) /* current working directory */
10910 + if (clewn_getwd(pathbuf, MAXPATHL))
10911 + dir = pathbuf;
10912 + else
10913 + dir = NULL;
10915 + else
10916 + dir = ptr;
10918 + if (dir != NULL)
10920 + obstack_strcat(obs, dir);
10921 + obstack_strcat(obs, "/");
10922 + obstack_strcat0(obs, name);
10923 + pathname = (char *)obstack_finish(obs);
10925 + if (stat((char *)pathname, &st) == 0) {
10926 + /* need to handle the case where the path includes '..'
10927 + * for example "/home/xavier/tmp/.." must be converted
10928 + * to "/home/xavier" */
10929 + if (clewn_fullpath(pathname, pathbuf, MAXPATHL, TRUE))
10930 + return (char *)obstack_strsave(obs, pathbuf);
10934 + ptr = last;
10935 + } while (ptr != NULL && *ptr != NUL);
10937 + return NULL;
10940 + /*
10941 + * Execute a program with (optionnaly quoted) arguments
10942 + */
10943 + void
10944 + clewn_exec(cmd)
10945 + char *cmd;
10947 + char ** argv = NULL; /* keep compiler happy */
10948 + char * newcmd;
10949 + int argc;
10950 + char * ptr;
10951 + int inquote;
10952 + int i;
10954 + if ((newcmd = clewn_strsave(cmd)) == NULL)
10955 + return;
10957 + /*
10958 + * step 1: find number of arguments
10959 + * step 2: separate them and built argv[]
10960 + */
10961 + for (i = 0; i < 2; i++)
10963 + ptr = newcmd;
10964 + argc = 0;
10966 + for (;;)
10968 + inquote = FALSE;
10970 + while (*ptr == ' ' || *ptr == '\t') /* skip to next non-white */
10971 + ptr++;
10973 + if (*ptr == '\0')
10974 + break;
10976 + if (*ptr == '"' || *ptr == '\'')
10978 + ptr++;
10979 + inquote = TRUE;
10982 + if (i == 1)
10983 + argv[argc] = ptr;
10985 + argc++;
10986 + while (*ptr && (inquote || (*ptr != ' ' && *ptr != '\t')))
10988 + if (*ptr == '"' || *ptr == '\'')
10989 + break;
10991 + ptr++;
10994 + if (*ptr == '\0')
10995 + break;
10997 + if (i == 1)
10998 + *ptr = '\0';
11000 + ptr++;
11003 + /* got the number of arguments */
11004 + if (i == 0 && (argv = (char **) xcalloc((size_t)((argc + 1) * sizeof(char *)))) == NULL)
11005 + return;
11008 + execvp(argv[0], argv);
11010 diff -c --new-file old/clewn/misc.h src/clewn/misc.h
11011 *** old/clewn/misc.h 1970-01-01 01:00:00.000000000 +0100
11012 --- src/clewn/misc.h 2007-07-21 18:35:40.000000000 +0200
11013 ***************
11014 *** 0 ****
11015 --- 1,92 ----
11016 + /* vi:set ts=8 sts=4 sw=4:
11018 + * Copyright (C) 2004 Xavier de Gaye.
11020 + * This program is free software; you can redistribute it and/or modify
11021 + * it under the terms of the GNU General Public License as published by
11022 + * the Free Software Foundation; either version 2, or (at your option)
11023 + * any later version.
11025 + * This program is distributed in the hope that it will be useful,
11026 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11027 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11028 + * GNU General Public License for more details.
11030 + * You should have received a copy of the GNU General Public License
11031 + * along with this program (see the file COPYING); if not, write to the
11032 + * Free Software Foundation, Inc.,
11033 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
11035 + * $Id: misc.h 148 2007-07-21 16:35:40Z xavier $
11036 + */
11038 + #ifndef MISC_H
11039 + # define MISC_H
11041 + #ifndef __ARGS
11042 + /* The AIX VisualAge cc compiler defines __EXTENDED__ instead of __STDC__
11043 + * because it includes pre-ansi features. */
11044 + # if defined(__STDC__) || defined(__GNUC__) || defined(__EXTENDED__)
11045 + # define __ARGS(x) x
11046 + # else
11047 + # define __ARGS(x) ()
11048 + # endif
11049 + #endif
11051 + /* memmove is not present on all systems, use memmove, bcopy, memcpy or our
11052 + * own version */
11053 + /* Some systems have (void *) arguments, some (char *). If we use (char *) it
11054 + * works for all */
11055 + #ifdef USEMEMMOVE
11056 + # define clewn_memmove(to, from, len) memmove((char *)(to), (char *)(from), len)
11057 + #else
11058 + # ifdef USEBCOPY
11059 + # define clewn_memmove(to, from, len) bcopy((char *)(from), (char *)(to), len)
11060 + # else
11061 + # ifdef USEMEMCPY
11062 + # define clewn_memmove(to, from, len) memcpy((char *)(to), (char *)(from), len)
11063 + # else
11064 + # define CLEWN_MEMMOVE
11065 + void clewn_memmove __ARGS((void *, void *, size_t));
11066 + # endif
11067 + # endif
11068 + #endif
11070 + #ifdef HAVE_MEMSET
11071 + # define clewn_memset(ptr, c, size) memset((ptr), (c), (size))
11072 + #else
11073 + void *clewn_memset __ARGS((void *, int, size_t));
11074 + #endif
11076 + /*
11077 + * Maximum length of a path (for non-unix systems) Make it a bit long, to stay
11078 + * on the safe side. But not too long to put on the stack.
11079 + */
11080 + #ifndef MAXPATHL
11081 + # ifdef MAXPATHLEN
11082 + # define MAXPATHL MAXPATHLEN
11083 + # else
11084 + # define MAXPATHL 256
11085 + # endif
11086 + #endif
11088 + /* gdb directory constants */
11089 + #define GDB_CDIR "$cdir"
11090 + #define GDB_CWD "$cwd"
11092 + void xatabort __ARGS((void (*)(void)));
11093 + void * xmalloc __ARGS((size_t));
11094 + void * xcalloc __ARGS((size_t));
11095 + void * xrealloc __ARGS((void *, size_t));
11096 + void xfree __ARGS((void *));
11097 + char * clewn_strsave __ARGS((char *));
11098 + char * clewn_strnsave __ARGS((char *, size_t));
11099 + void clewn_sleep __ARGS((int));
11100 + void clewn_beep __ARGS((void));
11101 + int clewn_getwd __ARGS((char *, int));
11102 + int clewn_fullpath __ARGS((char *, char *, int, int));
11103 + char * get_fullpath __ARGS((char *, char *, char *, char *, struct obstack *));
11104 + void clewn_exec(char *);
11106 + #endif /* MISC_H */
11108 diff -c --new-file old/clewn/obstack.c src/clewn/obstack.c
11109 *** old/clewn/obstack.c 1970-01-01 01:00:00.000000000 +0100
11110 --- src/clewn/obstack.c 2008-10-11 16:29:18.000000000 +0200
11111 ***************
11112 *** 0 ****
11113 --- 1,442 ----
11114 + /* obstack.c - subroutines used implicitly by object stack macros
11115 + Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
11116 + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
11117 + This file is part of the GNU C Library.
11119 + The GNU C Library is free software; you can redistribute it and/or
11120 + modify it under the terms of the GNU Lesser General Public
11121 + License as published by the Free Software Foundation; either
11122 + version 2.1 of the License, or (at your option) any later version.
11124 + The GNU C Library is distributed in the hope that it will be useful,
11125 + but WITHOUT ANY WARRANTY; without even the implied warranty of
11126 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11127 + Lesser General Public License for more details.
11129 + You should have received a copy of the GNU Lesser General Public
11130 + License along with the GNU C Library; if not, write to the Free
11131 + Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
11132 + Boston, MA 02110-1301, USA. */
11135 + #ifdef _LIBC
11136 + # include <obstack.h>
11137 + # include <shlib-compat.h>
11138 + #else
11139 + # ifdef HAVE_CONFIG_H
11140 + # ifdef HAVE_CLEWN
11141 + # include <config.h>
11142 + # else
11143 + # include <auto/config.h>
11144 + # endif
11145 + # endif
11146 + # include <stdint.h>
11147 + # include "obstack.h"
11148 + #endif
11150 + /* NOTE BEFORE MODIFYING THIS FILE: This version number must be
11151 + incremented whenever callers compiled using an old obstack.h can no
11152 + longer properly call the functions in this obstack.c. */
11153 + #define OBSTACK_INTERFACE_VERSION 1
11155 + /* Comment out all this code if we are using the GNU C Library, and are not
11156 + actually compiling the library itself, and the installed library
11157 + supports the same library interface we do. This code is part of the GNU
11158 + C Library, but also included in many other GNU distributions. Compiling
11159 + and linking in this code is a waste when using the GNU C library
11160 + (especially if it is a shared library). Rather than having every GNU
11161 + program understand `configure --with-gnu-libc' and omit the object
11162 + files, it is simpler to just do this in the source for each such file. */
11164 + #include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
11165 + #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
11166 + # include <gnu-versions.h>
11167 + # if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
11168 + # define ELIDE_CODE
11169 + # endif
11170 + #endif
11172 + #include <stddef.h>
11174 + #ifndef ELIDE_CODE
11177 + # if HAVE_INTTYPES_H
11178 + # include <inttypes.h>
11179 + # endif
11180 + # if HAVE_STDINT_H || defined _LIBC
11181 + # include <stdint.h>
11182 + # endif
11184 + /* Determine default alignment. */
11185 + union fooround
11187 + uintmax_t i;
11188 + long double d;
11189 + void *p;
11190 + };
11191 + struct fooalign
11193 + char c;
11194 + union fooround u;
11195 + };
11196 + /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
11197 + But in fact it might be less smart and round addresses to as much as
11198 + DEFAULT_ROUNDING. So we prepare for it to do that. */
11199 + enum
11201 + DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
11202 + DEFAULT_ROUNDING = sizeof (union fooround)
11203 + };
11205 + /* When we copy a long block of data, this is the unit to do it with.
11206 + On some machines, copying successive ints does not work;
11207 + in such a case, redefine COPYING_UNIT to `long' (if that works)
11208 + or `char' as a last resort. */
11209 + # ifndef COPYING_UNIT
11210 + # define COPYING_UNIT int
11211 + # endif
11214 + /* The functions allocating more room by calling `obstack_chunk_alloc'
11215 + jump to the handler pointed to by `obstack_alloc_failed_handler'.
11216 + This can be set to a user defined function which should either
11217 + abort gracefully or use longjump - but shouldn't return. This
11218 + variable by default points to the internal function
11219 + `print_and_abort'. */
11220 + static void print_and_abort (void);
11221 + void (*obstack_alloc_failed_handler) (void) = print_and_abort;
11223 + /* Exit value used when `print_and_abort' is used. */
11224 + # include <stdlib.h>
11225 + # ifdef _LIBC
11226 + int obstack_exit_failure = EXIT_FAILURE;
11227 + # else
11228 + # define obstack_exit_failure EXIT_FAILURE
11229 + # endif
11231 + # ifdef _LIBC
11232 + # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
11233 + /* A looong time ago (before 1994, anyway; we're not sure) this global variable
11234 + was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
11235 + library still exports it because somebody might use it. */
11236 + struct obstack *_obstack_compat;
11237 + compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
11238 + # endif
11239 + # endif
11241 + /* Define a macro that either calls functions with the traditional malloc/free
11242 + calling interface, or calls functions with the mmalloc/mfree interface
11243 + (that adds an extra first argument), based on the state of use_extra_arg.
11244 + For free, do not use ?:, since some compilers, like the MIPS compilers,
11245 + do not allow (expr) ? void : void. */
11247 + # define CALL_CHUNKFUN(h, size) \
11248 + (((h) -> use_extra_arg) \
11249 + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
11250 + : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
11252 + # define CALL_FREEFUN(h, old_chunk) \
11253 + do { \
11254 + if ((h) -> use_extra_arg) \
11255 + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
11256 + else \
11257 + (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
11258 + } while (0)
11260 + \f
11261 + /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
11262 + Objects start on multiples of ALIGNMENT (0 means use default).
11263 + CHUNKFUN is the function to use to allocate chunks,
11264 + and FREEFUN the function to free them.
11266 + Return nonzero if successful, calls obstack_alloc_failed_handler if
11267 + allocation fails. */
11269 + int
11270 + _obstack_begin (struct obstack *h,
11271 + int size, int alignment,
11272 + void *(*chunkfun) (long),
11273 + void (*freefun) (void *))
11275 + register struct _obstack_chunk *chunk; /* points to new chunk */
11277 + if (alignment == 0)
11278 + alignment = DEFAULT_ALIGNMENT;
11279 + if (size == 0)
11280 + /* Default size is what GNU malloc can fit in a 4096-byte block. */
11282 + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
11283 + Use the values for range checking, because if range checking is off,
11284 + the extra bytes won't be missed terribly, but if range checking is on
11285 + and we used a larger request, a whole extra 4096 bytes would be
11286 + allocated.
11288 + These number are irrelevant to the new GNU malloc. I suspect it is
11289 + less sensitive to the size of the request. */
11290 + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
11291 + + 4 + DEFAULT_ROUNDING - 1)
11292 + & ~(DEFAULT_ROUNDING - 1));
11293 + size = 4096 - extra;
11296 + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
11297 + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
11298 + h->chunk_size = size;
11299 + h->alignment_mask = alignment - 1;
11300 + h->use_extra_arg = 0;
11302 + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
11303 + if (!chunk)
11304 + (*obstack_alloc_failed_handler) ();
11305 + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
11306 + alignment - 1);
11307 + h->chunk_limit = chunk->limit
11308 + = (char *) chunk + h->chunk_size;
11309 + chunk->prev = 0;
11310 + /* The initial chunk now contains no empty object. */
11311 + h->maybe_empty_object = 0;
11312 + h->alloc_failed = 0;
11313 + return 1;
11316 + int
11317 + _obstack_begin_1 (struct obstack *h, int size, int alignment,
11318 + void *(*chunkfun) (void *, long),
11319 + void (*freefun) (void *, void *),
11320 + void *arg)
11322 + register struct _obstack_chunk *chunk; /* points to new chunk */
11324 + if (alignment == 0)
11325 + alignment = DEFAULT_ALIGNMENT;
11326 + if (size == 0)
11327 + /* Default size is what GNU malloc can fit in a 4096-byte block. */
11329 + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
11330 + Use the values for range checking, because if range checking is off,
11331 + the extra bytes won't be missed terribly, but if range checking is on
11332 + and we used a larger request, a whole extra 4096 bytes would be
11333 + allocated.
11335 + These number are irrelevant to the new GNU malloc. I suspect it is
11336 + less sensitive to the size of the request. */
11337 + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
11338 + + 4 + DEFAULT_ROUNDING - 1)
11339 + & ~(DEFAULT_ROUNDING - 1));
11340 + size = 4096 - extra;
11343 + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
11344 + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
11345 + h->chunk_size = size;
11346 + h->alignment_mask = alignment - 1;
11347 + h->extra_arg = arg;
11348 + h->use_extra_arg = 1;
11350 + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
11351 + if (!chunk)
11352 + (*obstack_alloc_failed_handler) ();
11353 + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
11354 + alignment - 1);
11355 + h->chunk_limit = chunk->limit
11356 + = (char *) chunk + h->chunk_size;
11357 + chunk->prev = 0;
11358 + /* The initial chunk now contains no empty object. */
11359 + h->maybe_empty_object = 0;
11360 + h->alloc_failed = 0;
11361 + return 1;
11364 + /* Allocate a new current chunk for the obstack *H
11365 + on the assumption that LENGTH bytes need to be added
11366 + to the current object, or a new object of length LENGTH allocated.
11367 + Copies any partial object from the end of the old chunk
11368 + to the beginning of the new one. */
11370 + void
11371 + _obstack_newchunk (struct obstack *h, int length)
11373 + register struct _obstack_chunk *old_chunk = h->chunk;
11374 + register struct _obstack_chunk *new_chunk;
11375 + register long new_size;
11376 + register long obj_size = h->next_free - h->object_base;
11377 + register long i;
11378 + long already;
11379 + char *object_base;
11381 + /* Compute size for new chunk. */
11382 + new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
11383 + if (new_size < h->chunk_size)
11384 + new_size = h->chunk_size;
11386 + /* Allocate and initialize the new chunk. */
11387 + new_chunk = CALL_CHUNKFUN (h, new_size);
11388 + if (!new_chunk)
11389 + (*obstack_alloc_failed_handler) ();
11390 + h->chunk = new_chunk;
11391 + new_chunk->prev = old_chunk;
11392 + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
11394 + /* Compute an aligned object_base in the new chunk */
11395 + object_base =
11396 + __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
11398 + /* Move the existing object to the new chunk.
11399 + Word at a time is fast and is safe if the object
11400 + is sufficiently aligned. */
11401 + if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
11403 + for (i = obj_size / sizeof (COPYING_UNIT) - 1;
11404 + i >= 0; i--)
11405 + ((COPYING_UNIT *)object_base)[i]
11406 + = ((COPYING_UNIT *)h->object_base)[i];
11407 + /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
11408 + but that can cross a page boundary on a machine
11409 + which does not do strict alignment for COPYING_UNITS. */
11410 + already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
11412 + else
11413 + already = 0;
11414 + /* Copy remaining bytes one by one. */
11415 + for (i = already; i < obj_size; i++)
11416 + object_base[i] = h->object_base[i];
11418 + /* If the object just copied was the only data in OLD_CHUNK,
11419 + free that chunk and remove it from the chain.
11420 + But not if that chunk might contain an empty object. */
11421 + if (! h->maybe_empty_object
11422 + && (h->object_base
11423 + == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
11424 + h->alignment_mask)))
11426 + new_chunk->prev = old_chunk->prev;
11427 + CALL_FREEFUN (h, old_chunk);
11430 + h->object_base = object_base;
11431 + h->next_free = h->object_base + obj_size;
11432 + /* The new chunk certainly contains no empty object yet. */
11433 + h->maybe_empty_object = 0;
11435 + # ifdef _LIBC
11436 + libc_hidden_def (_obstack_newchunk)
11437 + # endif
11439 + /* Return nonzero if object OBJ has been allocated from obstack H.
11440 + This is here for debugging.
11441 + If you use it in a program, you are probably losing. */
11443 + /* Suppress -Wmissing-prototypes warning. We don't want to declare this in
11444 + obstack.h because it is just for debugging. */
11445 + int _obstack_allocated_p (struct obstack *h, void *obj);
11447 + int
11448 + _obstack_allocated_p (struct obstack *h, void *obj)
11450 + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
11451 + register struct _obstack_chunk *plp; /* point to previous chunk if any */
11453 + lp = (h)->chunk;
11454 + /* We use >= rather than > since the object cannot be exactly at
11455 + the beginning of the chunk but might be an empty object exactly
11456 + at the end of an adjacent chunk. */
11457 + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
11459 + plp = lp->prev;
11460 + lp = plp;
11462 + return lp != 0;
11464 + \f
11465 + /* Free objects in obstack H, including OBJ and everything allocate
11466 + more recently than OBJ. If OBJ is zero, free everything in H. */
11468 + # undef obstack_free
11470 + void
11471 + obstack_free (struct obstack *h, void *obj)
11473 + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
11474 + register struct _obstack_chunk *plp; /* point to previous chunk if any */
11476 + lp = h->chunk;
11477 + /* We use >= because there cannot be an object at the beginning of a chunk.
11478 + But there can be an empty object at that address
11479 + at the end of another chunk. */
11480 + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
11482 + plp = lp->prev;
11483 + CALL_FREEFUN (h, lp);
11484 + lp = plp;
11485 + /* If we switch chunks, we can't tell whether the new current
11486 + chunk contains an empty object, so assume that it may. */
11487 + h->maybe_empty_object = 1;
11489 + if (lp)
11491 + h->object_base = h->next_free = (char *) (obj);
11492 + h->chunk_limit = lp->limit;
11493 + h->chunk = lp;
11495 + else if (obj != 0)
11496 + /* obj is not in any of the chunks! */
11497 + abort ();
11500 + # ifdef _LIBC
11501 + /* Older versions of libc used a function _obstack_free intended to be
11502 + called by non-GCC compilers. */
11503 + strong_alias (obstack_free, _obstack_free)
11504 + # endif
11505 + \f
11506 + int
11507 + _obstack_memory_used (struct obstack *h)
11509 + register struct _obstack_chunk* lp;
11510 + register int nbytes = 0;
11512 + for (lp = h->chunk; lp != 0; lp = lp->prev)
11514 + nbytes += lp->limit - (char *) lp;
11516 + return nbytes;
11518 + \f
11519 + /* Define the error handler. */
11520 + # ifdef _LIBC
11521 + # include <libintl.h>
11522 + # endif
11523 + # ifndef _
11524 + # define _(msgid) (msgid)
11525 + # endif
11527 + # ifdef _LIBC
11528 + # include <libio/iolibio.h>
11529 + # endif
11531 + # ifndef __attribute__
11532 + /* This feature is available in gcc versions 2.5 and later. */
11533 + # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
11534 + # define __attribute__(Spec) /* empty */
11535 + # endif
11536 + # endif
11538 + static void
11539 + __attribute__ ((noreturn))
11540 + print_and_abort (void)
11542 + /* Don't change any of these strings. Yes, it would be possible to add
11543 + the newline to the string and use fputs or so. But this must not
11544 + happen because the "memory exhausted" message appears in other places
11545 + like this and the translation should be reused instead of creating
11546 + a very similar string which requires a separate translation. */
11547 + # ifdef _LIBC
11548 + (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
11549 + # else
11550 + fprintf (stderr, "%s\n", _("memory exhausted"));
11551 + # endif
11552 + exit (obstack_exit_failure);
11555 + #endif /* !ELIDE_CODE */
11556 diff -c --new-file old/clewn/obstack.h src/clewn/obstack.h
11557 *** old/clewn/obstack.h 1970-01-01 01:00:00.000000000 +0100
11558 --- src/clewn/obstack.h 2006-07-29 19:19:30.000000000 +0200
11559 ***************
11560 *** 0 ****
11561 --- 1,509 ----
11562 + /* obstack.h - object stack macros
11563 + Copyright (C) 1988-1994,1996-1999,2003,2004,2005
11564 + Free Software Foundation, Inc.
11565 + This file is part of the GNU C Library.
11567 + The GNU C Library is free software; you can redistribute it and/or
11568 + modify it under the terms of the GNU Lesser General Public
11569 + License as published by the Free Software Foundation; either
11570 + version 2.1 of the License, or (at your option) any later version.
11572 + The GNU C Library is distributed in the hope that it will be useful,
11573 + but WITHOUT ANY WARRANTY; without even the implied warranty of
11574 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11575 + Lesser General Public License for more details.
11577 + You should have received a copy of the GNU Lesser General Public
11578 + License along with the GNU C Library; if not, write to the Free
11579 + Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
11580 + Boston, MA 02110-1301, USA. */
11582 + /* Summary:
11584 + All the apparent functions defined here are macros. The idea
11585 + is that you would use these pre-tested macros to solve a
11586 + very specific set of problems, and they would run fast.
11587 + Caution: no side-effects in arguments please!! They may be
11588 + evaluated MANY times!!
11590 + These macros operate a stack of objects. Each object starts life
11591 + small, and may grow to maturity. (Consider building a word syllable
11592 + by syllable.) An object can move while it is growing. Once it has
11593 + been "finished" it never changes address again. So the "top of the
11594 + stack" is typically an immature growing object, while the rest of the
11595 + stack is of mature, fixed size and fixed address objects.
11597 + These routines grab large chunks of memory, using a function you
11598 + supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
11599 + by calling `obstack_chunk_free'. You must define them and declare
11600 + them before using any obstack macros.
11602 + Each independent stack is represented by a `struct obstack'.
11603 + Each of the obstack macros expects a pointer to such a structure
11604 + as the first argument.
11606 + One motivation for this package is the problem of growing char strings
11607 + in symbol tables. Unless you are "fascist pig with a read-only mind"
11608 + --Gosper's immortal quote from HAKMEM item 154, out of context--you
11609 + would not like to put any arbitrary upper limit on the length of your
11610 + symbols.
11612 + In practice this often means you will build many short symbols and a
11613 + few long symbols. At the time you are reading a symbol you don't know
11614 + how long it is. One traditional method is to read a symbol into a
11615 + buffer, realloc()ating the buffer every time you try to read a symbol
11616 + that is longer than the buffer. This is beaut, but you still will
11617 + want to copy the symbol from the buffer to a more permanent
11618 + symbol-table entry say about half the time.
11620 + With obstacks, you can work differently. Use one obstack for all symbol
11621 + names. As you read a symbol, grow the name in the obstack gradually.
11622 + When the name is complete, finalize it. Then, if the symbol exists already,
11623 + free the newly read name.
11625 + The way we do this is to take a large chunk, allocating memory from
11626 + low addresses. When you want to build a symbol in the chunk you just
11627 + add chars above the current "high water mark" in the chunk. When you
11628 + have finished adding chars, because you got to the end of the symbol,
11629 + you know how long the chars are, and you can create a new object.
11630 + Mostly the chars will not burst over the highest address of the chunk,
11631 + because you would typically expect a chunk to be (say) 100 times as
11632 + long as an average object.
11634 + In case that isn't clear, when we have enough chars to make up
11635 + the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
11636 + so we just point to it where it lies. No moving of chars is
11637 + needed and this is the second win: potentially long strings need
11638 + never be explicitly shuffled. Once an object is formed, it does not
11639 + change its address during its lifetime.
11641 + When the chars burst over a chunk boundary, we allocate a larger
11642 + chunk, and then copy the partly formed object from the end of the old
11643 + chunk to the beginning of the new larger chunk. We then carry on
11644 + accreting characters to the end of the object as we normally would.
11646 + A special macro is provided to add a single char at a time to a
11647 + growing object. This allows the use of register variables, which
11648 + break the ordinary 'growth' macro.
11650 + Summary:
11651 + We allocate large chunks.
11652 + We carve out one object at a time from the current chunk.
11653 + Once carved, an object never moves.
11654 + We are free to append data of any size to the currently
11655 + growing object.
11656 + Exactly one object is growing in an obstack at any one time.
11657 + You can run one obstack per control block.
11658 + You may have as many control blocks as you dare.
11659 + Because of the way we do it, you can `unwind' an obstack
11660 + back to a previous state. (You may remove objects much
11661 + as you would with a stack.)
11662 + */
11665 + /* Don't do the contents of this file more than once. */
11667 + #ifndef _OBSTACK_H
11668 + #define _OBSTACK_H 1
11670 + #ifdef __cplusplus
11671 + extern "C" {
11672 + #endif
11673 + \f
11674 + /* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
11675 + defined, as with GNU C, use that; that way we don't pollute the
11676 + namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
11677 + and use ptrdiff_t. */
11679 + #ifdef __PTRDIFF_TYPE__
11680 + # define PTR_INT_TYPE __PTRDIFF_TYPE__
11681 + #else
11682 + # include <stddef.h>
11683 + # define PTR_INT_TYPE ptrdiff_t
11684 + #endif
11686 + /* If B is the base of an object addressed by P, return the result of
11687 + aligning P to the next multiple of A + 1. B and P must be of type
11688 + char *. A + 1 must be a power of 2. */
11690 + #define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
11692 + /* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case
11693 + where pointers can be converted to integers, aligned as integers,
11694 + and converted back again. If PTR_INT_TYPE is narrower than a
11695 + pointer (e.g., the AS/400), play it safe and compute the alignment
11696 + relative to B. Otherwise, use the faster strategy of computing the
11697 + alignment relative to 0. */
11699 + #define __PTR_ALIGN(B, P, A) \
11700 + __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
11701 + P, A)
11703 + #include <string.h>
11705 + struct _obstack_chunk /* Lives at front of each chunk. */
11707 + char *limit; /* 1 past end of this chunk */
11708 + struct _obstack_chunk *prev; /* address of prior chunk or NULL */
11709 + char contents[4]; /* objects begin here */
11710 + };
11712 + struct obstack /* control current object in current chunk */
11714 + long chunk_size; /* preferred size to allocate chunks in */
11715 + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
11716 + char *object_base; /* address of object we are building */
11717 + char *next_free; /* where to add next char to current object */
11718 + char *chunk_limit; /* address of char after current chunk */
11719 + union
11721 + PTR_INT_TYPE tempint;
11722 + void *tempptr;
11723 + } temp; /* Temporary for some macros. */
11724 + int alignment_mask; /* Mask of alignment for each object. */
11725 + /* These prototypes vary based on `use_extra_arg', and we use
11726 + casts to the prototypeless function type in all assignments,
11727 + but having prototypes here quiets -Wstrict-prototypes. */
11728 + struct _obstack_chunk *(*chunkfun) (void *, long);
11729 + void (*freefun) (void *, struct _obstack_chunk *);
11730 + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
11731 + unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
11732 + unsigned maybe_empty_object:1;/* There is a possibility that the current
11733 + chunk contains a zero-length object. This
11734 + prevents freeing the chunk if we allocate
11735 + a bigger chunk to replace it. */
11736 + unsigned alloc_failed:1; /* No longer used, as we now call the failed
11737 + handler on error, but retained for binary
11738 + compatibility. */
11739 + };
11741 + /* Declare the external functions we use; they are in obstack.c. */
11743 + extern void _obstack_newchunk (struct obstack *, int);
11744 + extern int _obstack_begin (struct obstack *, int, int,
11745 + void *(*) (long), void (*) (void *));
11746 + extern int _obstack_begin_1 (struct obstack *, int, int,
11747 + void *(*) (void *, long),
11748 + void (*) (void *, void *), void *);
11749 + extern int _obstack_memory_used (struct obstack *);
11751 + void obstack_free (struct obstack *obstack, void *block);
11753 + \f
11754 + /* Error handler called when `obstack_chunk_alloc' failed to allocate
11755 + more memory. This can be set to a user defined function which
11756 + should either abort gracefully or use longjump - but shouldn't
11757 + return. The default action is to print a message and abort. */
11758 + extern void (*obstack_alloc_failed_handler) (void);
11760 + /* Exit value used when `print_and_abort' is used. */
11761 + extern int obstack_exit_failure;
11762 + \f
11763 + /* Pointer to beginning of object being allocated or to be allocated next.
11764 + Note that this might not be the final address of the object
11765 + because a new chunk might be needed to hold the final size. */
11767 + #define obstack_base(h) ((void *) (h)->object_base)
11769 + /* Size for allocating ordinary chunks. */
11771 + #define obstack_chunk_size(h) ((h)->chunk_size)
11773 + /* Pointer to next byte not yet allocated in current chunk. */
11775 + #define obstack_next_free(h) ((h)->next_free)
11777 + /* Mask specifying low bits that should be clear in address of an object. */
11779 + #define obstack_alignment_mask(h) ((h)->alignment_mask)
11781 + /* To prevent prototype warnings provide complete argument list. */
11782 + #define obstack_init(h) \
11783 + _obstack_begin ((h), 0, 0, \
11784 + (void *(*) (long)) obstack_chunk_alloc, \
11785 + (void (*) (void *)) obstack_chunk_free)
11787 + #define obstack_begin(h, size) \
11788 + _obstack_begin ((h), (size), 0, \
11789 + (void *(*) (long)) obstack_chunk_alloc, \
11790 + (void (*) (void *)) obstack_chunk_free)
11792 + #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
11793 + _obstack_begin ((h), (size), (alignment), \
11794 + (void *(*) (long)) (chunkfun), \
11795 + (void (*) (void *)) (freefun))
11797 + #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
11798 + _obstack_begin_1 ((h), (size), (alignment), \
11799 + (void *(*) (void *, long)) (chunkfun), \
11800 + (void (*) (void *, void *)) (freefun), (arg))
11802 + #define obstack_chunkfun(h, newchunkfun) \
11803 + ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
11805 + #define obstack_freefun(h, newfreefun) \
11806 + ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
11808 + #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
11810 + #define obstack_blank_fast(h,n) ((h)->next_free += (n))
11812 + #define obstack_memory_used(h) _obstack_memory_used (h)
11813 + \f
11814 + #if defined __GNUC__ && defined __STDC__ && __STDC__
11815 + /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
11816 + does not implement __extension__. But that compiler doesn't define
11817 + __GNUC_MINOR__. */
11818 + # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
11819 + # define __extension__
11820 + # endif
11822 + /* For GNU C, if not -traditional,
11823 + we can define these macros to compute all args only once
11824 + without using a global variable.
11825 + Also, we can avoid using the `temp' slot, to make faster code. */
11827 + # define obstack_object_size(OBSTACK) \
11828 + __extension__ \
11829 + ({ struct obstack const *__o = (OBSTACK); \
11830 + (unsigned) (__o->next_free - __o->object_base); })
11832 + # define obstack_room(OBSTACK) \
11833 + __extension__ \
11834 + ({ struct obstack const *__o = (OBSTACK); \
11835 + (unsigned) (__o->chunk_limit - __o->next_free); })
11837 + # define obstack_make_room(OBSTACK,length) \
11838 + __extension__ \
11839 + ({ struct obstack *__o = (OBSTACK); \
11840 + int __len = (length); \
11841 + if (__o->chunk_limit - __o->next_free < __len) \
11842 + _obstack_newchunk (__o, __len); \
11843 + (void) 0; })
11845 + # define obstack_empty_p(OBSTACK) \
11846 + __extension__ \
11847 + ({ struct obstack const *__o = (OBSTACK); \
11848 + (__o->chunk->prev == 0 \
11849 + && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
11850 + __o->chunk->contents, \
11851 + __o->alignment_mask)); })
11853 + # define obstack_grow(OBSTACK,where,length) \
11854 + __extension__ \
11855 + ({ struct obstack *__o = (OBSTACK); \
11856 + int __len = (length); \
11857 + if (__o->next_free + __len > __o->chunk_limit) \
11858 + _obstack_newchunk (__o, __len); \
11859 + memcpy (__o->next_free, where, __len); \
11860 + __o->next_free += __len; \
11861 + (void) 0; })
11863 + # define obstack_grow0(OBSTACK,where,length) \
11864 + __extension__ \
11865 + ({ struct obstack *__o = (OBSTACK); \
11866 + int __len = (length); \
11867 + if (__o->next_free + __len + 1 > __o->chunk_limit) \
11868 + _obstack_newchunk (__o, __len + 1); \
11869 + memcpy (__o->next_free, where, __len); \
11870 + __o->next_free += __len; \
11871 + *(__o->next_free)++ = 0; \
11872 + (void) 0; })
11874 + # define obstack_1grow(OBSTACK,datum) \
11875 + __extension__ \
11876 + ({ struct obstack *__o = (OBSTACK); \
11877 + if (__o->next_free + 1 > __o->chunk_limit) \
11878 + _obstack_newchunk (__o, 1); \
11879 + obstack_1grow_fast (__o, datum); \
11880 + (void) 0; })
11882 + /* These assume that the obstack alignment is good enough for pointers
11883 + or ints, and that the data added so far to the current object
11884 + shares that much alignment. */
11886 + # define obstack_ptr_grow(OBSTACK,datum) \
11887 + __extension__ \
11888 + ({ struct obstack *__o = (OBSTACK); \
11889 + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
11890 + _obstack_newchunk (__o, sizeof (void *)); \
11891 + obstack_ptr_grow_fast (__o, datum); }) \
11893 + # define obstack_int_grow(OBSTACK,datum) \
11894 + __extension__ \
11895 + ({ struct obstack *__o = (OBSTACK); \
11896 + if (__o->next_free + sizeof (int) > __o->chunk_limit) \
11897 + _obstack_newchunk (__o, sizeof (int)); \
11898 + obstack_int_grow_fast (__o, datum); })
11900 + # define obstack_ptr_grow_fast(OBSTACK,aptr) \
11901 + __extension__ \
11902 + ({ struct obstack *__o1 = (OBSTACK); \
11903 + *(const void **) __o1->next_free = (aptr); \
11904 + __o1->next_free += sizeof (const void *); \
11905 + (void) 0; })
11907 + # define obstack_int_grow_fast(OBSTACK,aint) \
11908 + __extension__ \
11909 + ({ struct obstack *__o1 = (OBSTACK); \
11910 + *(int *) __o1->next_free = (aint); \
11911 + __o1->next_free += sizeof (int); \
11912 + (void) 0; })
11914 + # define obstack_blank(OBSTACK,length) \
11915 + __extension__ \
11916 + ({ struct obstack *__o = (OBSTACK); \
11917 + int __len = (length); \
11918 + if (__o->chunk_limit - __o->next_free < __len) \
11919 + _obstack_newchunk (__o, __len); \
11920 + obstack_blank_fast (__o, __len); \
11921 + (void) 0; })
11923 + # define obstack_alloc(OBSTACK,length) \
11924 + __extension__ \
11925 + ({ struct obstack *__h = (OBSTACK); \
11926 + obstack_blank (__h, (length)); \
11927 + obstack_finish (__h); })
11929 + # define obstack_copy(OBSTACK,where,length) \
11930 + __extension__ \
11931 + ({ struct obstack *__h = (OBSTACK); \
11932 + obstack_grow (__h, (where), (length)); \
11933 + obstack_finish (__h); })
11935 + # define obstack_copy0(OBSTACK,where,length) \
11936 + __extension__ \
11937 + ({ struct obstack *__h = (OBSTACK); \
11938 + obstack_grow0 (__h, (where), (length)); \
11939 + obstack_finish (__h); })
11941 + /* The local variable is named __o1 to avoid a name conflict
11942 + when obstack_blank is called. */
11943 + # define obstack_finish(OBSTACK) \
11944 + __extension__ \
11945 + ({ struct obstack *__o1 = (OBSTACK); \
11946 + void *__value = (void *) __o1->object_base; \
11947 + if (__o1->next_free == __value) \
11948 + __o1->maybe_empty_object = 1; \
11949 + __o1->next_free \
11950 + = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
11951 + __o1->alignment_mask); \
11952 + if (__o1->next_free - (char *)__o1->chunk \
11953 + > __o1->chunk_limit - (char *)__o1->chunk) \
11954 + __o1->next_free = __o1->chunk_limit; \
11955 + __o1->object_base = __o1->next_free; \
11956 + __value; })
11958 + # define obstack_free(OBSTACK, OBJ) \
11959 + __extension__ \
11960 + ({ struct obstack *__o = (OBSTACK); \
11961 + void *__obj = (OBJ); \
11962 + if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
11963 + __o->next_free = __o->object_base = (char *)__obj; \
11964 + else (obstack_free) (__o, __obj); })
11965 + \f
11966 + #else /* not __GNUC__ or not __STDC__ */
11968 + # define obstack_object_size(h) \
11969 + (unsigned) ((h)->next_free - (h)->object_base)
11971 + # define obstack_room(h) \
11972 + (unsigned) ((h)->chunk_limit - (h)->next_free)
11974 + # define obstack_empty_p(h) \
11975 + ((h)->chunk->prev == 0 \
11976 + && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
11977 + (h)->chunk->contents, \
11978 + (h)->alignment_mask))
11980 + /* Note that the call to _obstack_newchunk is enclosed in (..., 0)
11981 + so that we can avoid having void expressions
11982 + in the arms of the conditional expression.
11983 + Casting the third operand to void was tried before,
11984 + but some compilers won't accept it. */
11986 + # define obstack_make_room(h,length) \
11987 + ( (h)->temp.tempint = (length), \
11988 + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
11989 + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
11991 + # define obstack_grow(h,where,length) \
11992 + ( (h)->temp.tempint = (length), \
11993 + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
11994 + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
11995 + memcpy ((h)->next_free, where, (h)->temp.tempint), \
11996 + (h)->next_free += (h)->temp.tempint)
11998 + # define obstack_grow0(h,where,length) \
11999 + ( (h)->temp.tempint = (length), \
12000 + (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
12001 + ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
12002 + memcpy ((h)->next_free, where, (h)->temp.tempint), \
12003 + (h)->next_free += (h)->temp.tempint, \
12004 + *((h)->next_free)++ = 0)
12006 + # define obstack_1grow(h,datum) \
12007 + ( (((h)->next_free + 1 > (h)->chunk_limit) \
12008 + ? (_obstack_newchunk ((h), 1), 0) : 0), \
12009 + obstack_1grow_fast (h, datum))
12011 + # define obstack_ptr_grow(h,datum) \
12012 + ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
12013 + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
12014 + obstack_ptr_grow_fast (h, datum))
12016 + # define obstack_int_grow(h,datum) \
12017 + ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
12018 + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
12019 + obstack_int_grow_fast (h, datum))
12021 + # define obstack_ptr_grow_fast(h,aptr) \
12022 + (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
12024 + # define obstack_int_grow_fast(h,aint) \
12025 + (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
12027 + # define obstack_blank(h,length) \
12028 + ( (h)->temp.tempint = (length), \
12029 + (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
12030 + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
12031 + obstack_blank_fast (h, (h)->temp.tempint))
12033 + # define obstack_alloc(h,length) \
12034 + (obstack_blank ((h), (length)), obstack_finish ((h)))
12036 + # define obstack_copy(h,where,length) \
12037 + (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
12039 + # define obstack_copy0(h,where,length) \
12040 + (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
12042 + # define obstack_finish(h) \
12043 + ( ((h)->next_free == (h)->object_base \
12044 + ? (((h)->maybe_empty_object = 1), 0) \
12045 + : 0), \
12046 + (h)->temp.tempptr = (h)->object_base, \
12047 + (h)->next_free \
12048 + = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
12049 + (h)->alignment_mask), \
12050 + (((h)->next_free - (char *) (h)->chunk \
12051 + > (h)->chunk_limit - (char *) (h)->chunk) \
12052 + ? ((h)->next_free = (h)->chunk_limit) : 0), \
12053 + (h)->object_base = (h)->next_free, \
12054 + (h)->temp.tempptr)
12056 + # define obstack_free(h,obj) \
12057 + ( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
12058 + ((((h)->temp.tempint > 0 \
12059 + && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
12060 + ? (int) ((h)->next_free = (h)->object_base \
12061 + = (h)->temp.tempint + (char *) (h)->chunk) \
12062 + : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0)))
12064 + #endif /* not __GNUC__ or not __STDC__ */
12066 + #ifdef __cplusplus
12067 + } /* C++ */
12068 + #endif
12070 + #endif /* obstack.h */