39bdebf7b1ab42bda110e2449f075c4fa808bdd8
[gdbmicli.git] / examples / x11_wp_test.c
1 /**[txh]********************************************************************
2
3   Copyright (c) 2004 by Salvador E. Tropea.
4   Covered by the GPL license.
5
6   Comment:
7   X11 example/test of the libmigdb.
8   Run it from an X11 terminal (xterm, Eterm, etc.).
9   
10 ***************************************************************************/
11
12 #include <stdio.h>
13 #include <unistd.h> //usleep
14 #include "mi_gdb.h"
15
16 void cb_console(const char *str, void *data)
17 {
18  printf("CONSOLE> %s\n",str);
19 }
20
21 /* Note that unlike what's documented in gdb docs it isn't usable. */
22 void cb_target(const char *str, void *data)
23 {
24  printf("TARGET> %s\n",str);
25 }
26
27 void cb_log(const char *str, void *data)
28 {
29  printf("LOG> %s\n",str);
30 }
31
32 void cb_to(const char *str, void *data)
33 {
34  printf(">> %s",str);
35 }
36
37 void cb_from(const char *str, void *data)
38 {
39  printf("<< %s\n",str);
40 }
41
42 volatile int async_c=0;
43
44 void cb_async(mi_output *o, void *data)
45 {
46  printf("ASYNC\n");
47  async_c++;
48 }
49
50 void print_frames(mi_frames *f)
51 {
52  if (!f)
53    {
54     printf("Error! empty frames info\n");
55     return;
56    }
57  while (f)
58    {
59     printf("Level %d, addr %p, func %s, where: %s:%d args? %c\n",f->level,f->addr,
60            f->func,f->file,f->line,f->args ? 'y' : 'n');
61     f=f->next;
62    }
63  mi_free_frames(f);
64 }
65
66 int wait_for_stop(mi_h *h)
67 {
68  int res=1;
69  mi_stop *sr;
70
71  while (!mi_get_response(h))
72     usleep(1000);
73  /* The end of the async. */
74  sr=mi_res_stop(h);
75  if (sr)
76    {
77     printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
78     print_frames(sr->frame);
79     mi_free_stop(sr);
80    }
81  else
82    {
83     printf("Error while waiting\n");
84     printf("mi_error: %s (%d)\nmi_error_from_gdb: %s\n",mi_get_error_str(),
85            mi_error,mi_error_from_gdb);
86     res=0;
87    }
88  return res;
89 }
90
91
92 void print_gvar(mi_gvar *v)
93 {
94  if (!v)
95    {
96     printf("Error! failed to define variable\n");
97     return;
98    }
99  printf("Variable name: '%s', type: '%s', number of children: %d format: %s expression: %s lang: %s editable: %c\n",
100         v->name,v->type,v->numchild,mi_format_enum_to_str(v->format),
101         v->exp,mi_lang_enum_to_str(v->lang),v->attr & MI_ATTR_EDITABLE ? 'y' : 'n');
102 }
103
104 void print_update(mi_gvar_chg *changed)
105 {
106  printf("List of changed variables:\n");
107  while (changed)
108    {
109     printf("Name: %s\nIn scope: %c\n",changed->name,changed->in_scope ? 'y' : 'n');
110     if (changed->in_scope && changed->new_type)
111       {
112        printf("New type: %s\nNew num children: %d\n",changed->new_type,changed->new_num_children);
113       }
114     changed=changed->next;
115     printf("\n");
116    }
117 }
118
119 void print_children(mi_gvar *ch)
120 {
121  int i;
122  mi_gvar *s;
123
124  if (!ch->child)
125    {
126     printf("Error! getting children list\n");
127     return;
128    }
129  printf("\nChildren List (%d):\n",ch->numchild);
130  for (i=0, s=ch->child; i<ch->numchild; s++, i++)
131     {
132      printf("Name: %s Exp: %s Children: %d",s->name,s->exp,s->numchild);
133      if (s->type)
134         printf(" Type: %s",s->type);
135      if (s->value)
136         printf(" Value: %s",s->value);
137      printf("\n");
138     }
139  printf("\n");
140 }
141
142 enum cont_mode { cm_run, cm_continue, cm_finish, cm_step };
143
144 void do_continue(mi_h *h, enum cont_mode mode)
145 {
146  int res;
147  switch (mode)
148    {
149     case cm_run:
150          res=gmi_exec_run(h);
151          break;
152     case cm_continue:
153          res=gmi_exec_continue(h);
154          break;
155     case cm_finish:
156          res=gmi_exec_finish(h);
157          break;
158     case cm_step:
159          res=gmi_exec_step(h);
160          break;
161    }
162  /* Continue the program. */
163  if (!res)
164    {
165     printf("Error in run!\n");
166     mi_disconnect(h);
167     exit(1);
168    }
169  /* Here we should be stopped at the breakpoint. */
170  if (!wait_for_stop(h))
171    {
172     mi_disconnect(h);
173     exit(1);
174    }
175 }
176
177
178 int main(int argc, char *argv[])
179 {
180  mi_aux_term *xterm_tty=NULL;
181  /* This is like a file-handle for fopen.
182     Here we have all the state of gdb "connection". */
183  mi_h *h;
184  mi_bkpt *bk;
185  mi_wp *wp, *wp2;
186
187  /* You can use any gdb you want: */
188  /*mi_set_gdb_exe("/usr/src/gdb-6.1.1/gdb/gdb");*/
189  /* You can use a terminal different than xterm: */
190  /*mi_set_xterm_exe("/usr/bin/Eterm");*/
191
192  /* Connect to gdb child. */
193  h=mi_connect_local();
194  if (!h)
195    {
196     printf("Connect failed\n");
197     return 1;
198    }
199  printf("Connected to gdb!\n");
200
201  /* Set all callbacks. */
202  mi_set_console_cb(h,cb_console,NULL);
203  mi_set_target_cb(h,cb_target,NULL);
204  mi_set_log_cb(h,cb_log,NULL);
205  mi_set_async_cb(h,cb_async,NULL);
206  mi_set_to_gdb_cb(h,cb_to,NULL);
207  mi_set_from_gdb_cb(h,cb_from,NULL);
208
209  /* Open an xterm to be used as terminal for the debuggy. */
210  xterm_tty=gmi_start_xterm();
211  if (!xterm_tty)
212     printf("Error opening auxiliar terminal, we'll use current one.\n");
213  else
214     printf("XTerm opened @ %s\n",xterm_tty->tty);
215
216  /* Tell gdb to attach the child to a terminal. */
217  if (!gmi_target_terminal(h,xterm_tty ? xterm_tty->tty : ttyname(STDIN_FILENO)))
218    {
219     printf("Error selecting target terminal\n");
220     mi_disconnect(h);
221     return 1;
222    }
223
224  /* Set the name of the child and the command line aguments. */
225  if (!gmi_set_exec(h,"./target_frames",""))
226    {
227     printf("Error setting exec y args\n");
228     mi_disconnect(h);
229     return 1;
230    }
231
232  /* Break on FuncLev1. */
233  bk=gmi_break_insert_full(h,1,0,NULL,-1,-1,"FuncLev1");
234  if (!bk)
235    {
236     printf("Error setting breakpoint\n");
237     mi_disconnect(h);
238     return 1;
239    }
240  printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
241  mi_free_bkpt(bk);
242
243  /* Set a watchpoint, that's a data breakpoint. */
244  wp=gmi_break_watch(h,wm_write,"v");
245  if (!wp)
246    {
247     printf("Error al setting watchpoint\n");
248     mi_disconnect(h);
249     return 1;
250    }
251  printf("Watchpoint %d for expression: %s\n",wp->number,wp->exp);
252  mi_free_wp(wp);
253
254  /* Run the program. */
255  do_continue(h,cm_run);
256
257  wp2=gmi_break_watch(h,wm_write,"i");
258  mi_free_wp(wp2);
259
260  if (1)
261    {
262     do_continue(h,cm_finish);
263     do_continue(h,cm_finish);
264     do_continue(h,cm_finish);
265     do_continue(h,cm_continue);
266     do_continue(h,cm_continue);
267     do_continue(h,cm_step);
268     do_continue(h,cm_step);
269     do_continue(h,cm_step);
270     do_continue(h,cm_step);
271     do_continue(h,cm_step);
272     do_continue(h,cm_step);
273     do_continue(h,cm_step);
274    }
275  else
276    {
277     do_continue(h,cm_step);
278     do_continue(h,cm_step);
279     do_continue(h,cm_step);
280    }
281
282  /* Exit from gdb. */
283  gmi_gdb_exit(h);
284  /* Close the connection. */
285  mi_disconnect(h);
286  /* Wait 5 seconds and close the auxiliar terminal. */
287  printf("Waiting 5 seconds\n");
288  //sleep(5);
289  gmi_end_aux_term(xterm_tty);
290
291  return 0;
292 }