aboutsummaryrefslogtreecommitdiff
path: root/pathologist/src/mi/gdbmi_parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'pathologist/src/mi/gdbmi_parse.c')
-rw-r--r--pathologist/src/mi/gdbmi_parse.c1927
1 files changed, 1927 insertions, 0 deletions
diff --git a/pathologist/src/mi/gdbmi_parse.c b/pathologist/src/mi/gdbmi_parse.c
new file mode 100644
index 0000000..d30bd22
--- /dev/null
+++ b/pathologist/src/mi/gdbmi_parse.c
@@ -0,0 +1,1927 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2007 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Parser.
7 Comments:
8 Parses the output of gdb. It basically converts the text from gdb into a
9tree (could be a complex one) that we can easily interpret using C code.
10
11***************************************************************************/
12
13#include <ctype.h>
14#include <string.h>
15#include <assert.h>
16#include "gdbmi.h"
17
18mi_results *mi_get_result(const char *str, const char **end);
19int mi_get_value(mi_results *r, const char *str, const char **end);
20
21
22/* GDB BUG!!!! I got:
23^error,msg="Problem parsing arguments: data-evaluate-expression ""1+2"""
24Afects gdb 2002-04-01-cvs and 6.1.1 for sure.
25That's an heuristical workaround.
26*/
27static inline
28int EndOfStr(const char *s)
29{
30 if (*s=='"')
31 {
32 s++;
33 return !*s || *s==',' || *s==']' || *s=='}';
34 }
35 return 0;
36}
37
38int mi_get_cstring_r(mi_results *r, const char *str, const char **end)
39{
40 const char *s;
41 char *d;
42 int len;
43
44 if (*str!='"')
45 {
46 mi_error=MI_PARSER;
47 return 0;
48 }
49 str++;
50 /* Meassure. */
51 for (s=str, len=0; *s && !EndOfStr(s); s++)
52 {
53 if (!*s) {
54 mi_error = MI_PARSER;
55 return 0;
56 }
57 if (*s=='\\')
58 s++;
59 len++;
60 }
61 /* Copy. */
62 r->type=t_const;
63 d=r->v.cstr=mi_malloc(len+1);
64 if (!r->v.cstr)
65 return 0;
66 for (s=str; *s && !EndOfStr(s); s++, d++)
67 {
68 if (*s=='\\')
69 {
70 s++;
71 switch (*s)
72 {
73 case 'n':
74 *d='\n';
75 break;
76 case 't':
77 *d='\t';
78 break;
79 default:
80 *d=*s;
81 }
82 }
83 else
84 *d=*s;
85 }
86 *d=0;
87 if (end)
88 *end=s+1;
89
90 return 1;
91}
92
93/* TODO: What's a valid variable name?
94 I'll assume a-zA-Z0-9_- */
95//inline
96int mi_is_var_name_char(char c)
97{
98 return isalnum(c) || c=='-' || c=='_';
99}
100
101char *mi_get_var_name(const char *str, const char **end)
102{
103 const char *s;
104 char *r;
105 int l;
106 /* Meassure. */
107 for (s=str; *s && mi_is_var_name_char(*s); s++);
108 if (*s!='=')
109 {
110 mi_error=MI_PARSER;
111 return NULL;
112 }
113 /* Allocate. */
114 l=s-str;
115 r=mi_malloc(l+1);
116 /* Copy. */
117 if (NULL != r) {
118 memcpy(r,str,l);
119 r[l]=0;
120 }
121 if (end)
122 *end=s+1;
123 return r;
124}
125
126
127int mi_get_list_res(mi_results *r, const char *str, const char **end, char closeC)
128{
129 mi_results *last_r, *rs;
130
131 last_r=NULL;
132 do
133 {
134 rs=mi_get_result(str,&str);
135 if (last_r)
136 last_r->next=rs;
137 else
138 r->v.rs=rs;
139 last_r=rs;
140 if (*str==closeC)
141 {
142 *end=str+1;
143 return 1;
144 }
145 if (*str!=',')
146 break;
147 str++;
148 }
149 while (1);
150
151 mi_error=MI_PARSER;
152 return 0;
153}
154
155#ifdef __APPLE__
156int mi_get_tuple_val(mi_results *r, const char *str, const char **end)
157{
158 mi_results *last_r, *rs;
159
160 last_r=NULL;
161 do
162 {
163 rs=mi_alloc_results();
164 if (!rs || !mi_get_value(rs,str,&str))
165 {
166 mi_free_results(rs);
167 return 0;
168 }
169 /* Note that rs->var is NULL, that indicates that's just a value and not
170 a result. */
171 if (last_r)
172 last_r->next=rs;
173 else
174 r->v.rs=rs;
175 last_r=rs;
176 if (*str=='}')
177 {
178 *end=str+1;
179 return 1;
180 }
181 if (*str!=',')
182 break;
183 str++;
184 }
185 while (1);
186
187 mi_error=MI_PARSER;
188 return 0;
189}
190#endif /* __APPLE__ */
191
192int mi_get_tuple(mi_results *r, const char *str, const char **end)
193{
194 if (*str!='{')
195 {
196 mi_error=MI_PARSER;
197 return 0;
198 }
199 r->type=t_tuple;
200 str++;
201 if (*str=='}')
202 {/* Special case: empty tuple */
203 *end=str+1;
204 return 1;
205 }
206 #ifdef __APPLE__
207 if (mi_is_var_name_char(*str))
208 return mi_get_list_res(r,str,end,'}');
209 return mi_get_tuple_val(r,str,end);
210 #else /* __APPLE__ */
211 return mi_get_list_res(r,str,end,'}');
212 #endif /* __APPLE__ */
213}
214
215int mi_get_list_val(mi_results *r, const char *str, const char **end)
216{
217 mi_results *last_r, *rs;
218
219 last_r=NULL;
220 do
221 {
222 rs=mi_alloc_results();
223 if (!rs || !mi_get_value(rs,str,&str))
224 {
225 mi_free_results(rs);
226 return 0;
227 }
228 /* Note that rs->var is NULL, that indicates that's just a value and not
229 a result. */
230 if (last_r)
231 last_r->next=rs;
232 else
233 r->v.rs=rs;
234 last_r=rs;
235 if (*str==']')
236 {
237 *end=str+1;
238 return 1;
239 }
240 if (*str!=',')
241 break;
242 str++;
243 }
244 while (1);
245
246 mi_error=MI_PARSER;
247 return 0;
248}
249
250int mi_get_list(mi_results *r, const char *str, const char **end)
251{
252 if (*str!='[')
253 {
254 mi_error=MI_PARSER;
255 return 0;
256 }
257 r->type=t_list;
258 str++;
259 if (*str==']')
260 {/* Special case: empty list */
261 *end=str+1;
262 return 1;
263 }
264 /* Comment: I think they could choose () for values. Is confusing in this way. */
265 if (mi_is_var_name_char(*str))
266 return mi_get_list_res(r,str,end,']');
267 return mi_get_list_val(r,str,end);
268}
269
270int mi_get_value(mi_results *r, const char *str, const char **end)
271{
272 switch (str[0])
273 {
274 case '"':
275 return mi_get_cstring_r(r,str,end);
276 case '{':
277 return mi_get_tuple(r,str,end);
278 case '[':
279 return mi_get_list(r,str,end);
280 }
281 mi_error=MI_PARSER;
282 return 0;
283}
284
285mi_results *mi_get_result(const char *str, const char **end)
286{
287 char *var;
288 mi_results *r;
289
290 var=mi_get_var_name(str,&str);
291 if (!var)
292 return NULL;
293
294 r=mi_alloc_results();
295 if (!r)
296 {
297 free(var);
298 return NULL;
299 }
300 r->var=var;
301
302 if (!mi_get_value(r,str,end))
303 {
304 mi_free_results(r);
305 return NULL;
306 }
307
308 return r;
309}
310
311mi_output *mi_get_results_alone(mi_output *r,const char *str)
312{
313 mi_results *last_r, *rs;
314
315 /* * results */
316 last_r=NULL;
317 do
318 {
319 if (!*str)
320 return r;
321 if (*str!=',')
322 {
323 mi_error=MI_PARSER;
324 break;
325 }
326 str++;
327 rs=mi_get_result(str,&str);
328 if (!rs)
329 break;
330 if (!last_r)
331 r->c=rs;
332 else
333 last_r->next=rs;
334 last_r=rs;
335 }
336 while (1);
337 mi_free_output(r);
338 return NULL;
339}
340
341mi_output *mi_parse_result_record(mi_output *r,const char *str)
342{
343 r->type=MI_T_RESULT_RECORD;
344
345 /* Solve the result-class. */
346 if (strncmp(str,"done",4)==0)
347 {
348 str+=4;
349 r->tclass=MI_CL_DONE;
350 }
351 else if (strncmp(str,"running",7)==0)
352 {
353 str+=7;
354 r->tclass=MI_CL_RUNNING;
355 }
356 else if (strncmp(str,"connected",9)==0)
357 {
358 str+=9;
359 r->tclass=MI_CL_CONNECTED;
360 }
361 else if (strncmp(str,"error",5)==0)
362 {
363 str+=5;
364 r->tclass=MI_CL_ERROR;
365 }
366 else if (strncmp(str,"exit",4)==0)
367 {
368 str+=4;
369 r->tclass=MI_CL_EXIT;
370 }
371 else
372 {
373 mi_error=MI_UNKNOWN_RESULT;
374 return NULL;
375 }
376
377 return mi_get_results_alone(r,str);
378}
379
380mi_output *mi_parse_asyn(mi_output *r,const char *str)
381{
382 r->type=MI_T_OUT_OF_BAND;
383 r->stype=MI_ST_ASYNC;
384 /* async-class. */
385 if (strncmp(str,"stopped",7)==0)
386 {
387 r->tclass=MI_CL_STOPPED;
388 str+=7;
389 return mi_get_results_alone(r,str);
390 }
391 if (strncmp(str,"download",8)==0)
392 {
393 r->tclass=MI_CL_DOWNLOAD;
394 str+=8;
395 return mi_get_results_alone(r,str);
396 }
397 mi_error=MI_UNKNOWN_ASYNC;
398 mi_free_output(r);
399 return NULL;
400}
401
402mi_output *mi_parse_exec_asyn(mi_output *r,const char *str)
403{
404 r->sstype=MI_SST_EXEC;
405 return mi_parse_asyn(r,str);
406}
407
408mi_output *mi_parse_status_asyn(mi_output *r,const char *str)
409{
410 r->sstype=MI_SST_STATUS;
411 return mi_parse_asyn(r,str);
412}
413
414mi_output *mi_parse_notify_asyn(mi_output *r,const char *str)
415{
416 r->sstype=MI_SST_NOTIFY;
417 return mi_parse_asyn(r,str);
418}
419
420mi_output *mi_console(mi_output *r,const char *str)
421{
422 r->type=MI_T_OUT_OF_BAND;
423 r->stype=MI_ST_STREAM;
424 r->c=mi_alloc_results();
425 if (!r->c || !mi_get_cstring_r(r->c,str,NULL))
426 {
427 mi_free_output(r);
428 return NULL;
429 }
430 return r;
431}
432
433mi_output *mi_console_stream(mi_output *r,const char *str)
434{
435 r->sstype=MI_SST_CONSOLE;
436 return mi_console(r,str);
437}
438
439mi_output *mi_target_stream(mi_output *r,const char *str)
440{
441 r->sstype=MI_SST_TARGET;
442 return mi_console(r,str);
443}
444
445mi_output *mi_log_stream(mi_output *r,const char *str)
446{
447 r->sstype=MI_SST_LOG;
448 return mi_console(r,str);
449}
450
451mi_output *mi_parse_gdb_output(const char *str)
452{
453 char type=str[0];
454
455 mi_output *r=mi_alloc_output();
456 if (!r)
457 {
458 mi_error=MI_OUT_OF_MEMORY;
459 return NULL;
460 }
461 str++;
462 switch (type)
463 {
464 case '^':
465 return mi_parse_result_record(r,str);
466 case '*':
467 return mi_parse_exec_asyn(r,str);
468 case '+':
469 return mi_parse_status_asyn(r,str);
470 case '=':
471 return mi_parse_notify_asyn(r,str);
472 case '~':
473 return mi_console_stream(r,str);
474 case '@':
475 return mi_target_stream(r,str);
476 case '&':
477 return mi_log_stream(r,str);
478 }
479 mi_error=MI_PARSER;
480 return NULL;
481}
482
483mi_output *mi_get_rrecord(mi_output *r)
484{
485 if (!r)
486 return NULL;
487 while (r)
488 {
489 if (r->type==MI_T_RESULT_RECORD)
490 return r;
491 r=r->next;
492 }
493 return r;
494}
495
496mi_results *mi_get_var_r(mi_results *r, const char *var)
497{
498 while (r)
499 {
500 if (strcmp(r->var,var)==0)
501 return r;
502 r=r->next;
503 }
504 return NULL;
505}
506
507mi_results *mi_get_var(mi_output *res, const char *var)
508{
509 if (!res)
510 return NULL;
511 return mi_get_var_r(res->c,var);
512}
513
514int mi_get_async_stop_reason(mi_output *r, char **reason)
515{
516 int found_stopped=0;
517
518 *reason=NULL;
519 while (r)
520 {
521 if (r->type==MI_T_RESULT_RECORD && r->tclass==MI_CL_ERROR)
522 {
523 if (r->c->type==t_const)
524 *reason=r->c->v.cstr;
525 return 0;
526 }
527 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
528 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
529 {
530 mi_results *p=r->c;
531 found_stopped=1;
532 while (p)
533 {
534 if (strcmp(p->var,"reason")==0)
535 {
536 *reason=p->v.cstr;
537 return 1;
538 }
539 p=p->next;
540 }
541 }
542 r=r->next;
543 }
544 if (*reason==NULL && found_stopped)
545 {
546 *reason=strdup("unknown (temp bkpt?)");
547 return 1;
548 }
549 return 0;
550}
551
552mi_frames *mi_get_async_frame(mi_output *r)
553{
554 while (r)
555 {
556 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
557 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
558 {
559 mi_results *p=r->c;
560 while (p)
561 {
562 if (strcmp(p->var,"frame")==0)
563 return mi_parse_frame(p->v.rs);
564 p=p->next;
565 }
566 }
567 r=r->next;
568 }
569 return NULL;
570}
571
572int mi_res_simple(mi_h *h, int tclass, int accert_ret)
573{
574 mi_output *r, *res;
575 int ret=0;
576
577 r=mi_get_response_blk(h);
578 res=mi_get_rrecord(r);
579
580 if (res)
581 ret=res->tclass==tclass;
582 mi_free_output(r);
583
584 return ret;
585}
586
587
588int mi_res_simple_done(mi_h *h)
589{
590 return mi_res_simple(h,MI_CL_DONE,0);
591}
592
593int mi_res_simple_exit(mi_h *h)
594{
595 return mi_res_simple(h,MI_CL_EXIT,1);
596}
597
598int mi_res_simple_running(mi_h *h)
599{
600 return mi_res_simple(h,MI_CL_RUNNING,0);
601}
602
603int mi_res_simple_connected(mi_h *h)
604{
605 return mi_res_simple(h,MI_CL_CONNECTED,0);
606}
607
608mi_results *mi_res_var(mi_h *h, const char *var, int tclass)
609{
610 mi_output *r, *res;
611 mi_results *the_var=NULL;
612
613 r=mi_get_response_blk(h);
614 /* All the code that follows is "NULL" tolerant. */
615 /* Look for the result-record. */
616 res=mi_get_rrecord(r);
617 /* Look for the desired var. */
618 if (res && res->tclass==tclass)
619 the_var=mi_get_var(res,var);
620 /* Release all but the one we want. */
621 mi_free_output_but(r,NULL,the_var);
622 return the_var;
623}
624
625mi_results *mi_res_done_var(mi_h *h, const char *var)
626{
627 return mi_res_var(h,var,MI_CL_DONE);
628}
629
630mi_frames *mi_parse_frame(mi_results *c)
631{
632 mi_frames *res=mi_alloc_frames();
633 char *end;
634
635 if (res)
636 {
637 while (c)
638 {
639 if (c->type==t_const)
640 {
641 if (strcmp(c->var,"level")==0)
642 res->level=atoi(c->v.cstr);
643 else if (strcmp(c->var,"addr")==0)
644 res->addr=(void *)strtoul(c->v.cstr,&end,0);
645 else if (strcmp(c->var,"func")==0)
646 {
647 res->func=c->v.cstr;
648 c->v.cstr=NULL;
649 }
650 else if (strcmp(c->var,"file")==0)
651 {
652 res->file=c->v.cstr;
653 c->v.cstr=NULL;
654 }
655 else if (strcmp(c->var,"from")==0)
656 {
657 res->from=c->v.cstr;
658 c->v.cstr=NULL;
659 }
660 else if (strcmp(c->var,"line")==0)
661 res->line=atoi(c->v.cstr);
662 }
663 else if (c->type==t_list && strcmp(c->var,"args")==0)
664 {
665 res->args=c->v.rs;
666 c->v.rs=NULL;
667 }
668 c=c->next;
669 }
670 }
671 return res;
672}
673
674mi_frames *mi_res_frame(mi_h *h)
675{
676 mi_results *r=mi_res_done_var(h,"frame");
677 mi_frames *f=NULL;
678
679 if (r && r->type==t_tuple)
680 f=mi_parse_frame(r->v.rs);
681 mi_free_results(r);
682 return f;
683}
684
685mi_frames *mi_res_frames_array(mi_h *h, const char *var)
686{
687 mi_results *r=mi_res_done_var(h,var), *c;
688 mi_frames *res=NULL, *nframe, *last=NULL;
689
690 if (!r)
691 return NULL;
692#ifdef __APPLE__
693 if (r->type!=t_list && r->type!=t_tuple)
694#else
695 if (r->type!=t_list)
696#endif
697 {
698 mi_free_results(r);
699 return NULL;
700 }
701 c=r->v.rs;
702 while (c)
703 {
704 if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
705 {
706 nframe=mi_parse_frame(c->v.rs);
707 if (nframe)
708 {
709 if (!last)
710 res=nframe;
711 else
712 last->next=nframe;
713 last=nframe;
714 }
715 }
716 c=c->next;
717 }
718 mi_free_results(r);
719 return res;
720}
721
722mi_frames *mi_res_frames_list(mi_h *h)
723{
724 mi_output *r, *res;
725 mi_frames *ret=NULL, *nframe, *last=NULL;
726 mi_results *c;
727
728 r=mi_get_response_blk(h);
729 res=mi_get_rrecord(r);
730 if (res && res->tclass==MI_CL_DONE)
731 {
732 c=res->c;
733 while (c)
734 {
735 if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
736 {
737 nframe=mi_parse_frame(c->v.rs);
738 if (nframe)
739 {
740 if (!last)
741 ret=nframe;
742 else
743 last->next=nframe;
744 last=nframe;
745 }
746 }
747 c=c->next;
748 }
749 }
750 mi_free_output(r);
751 return ret;
752}
753
754int mi_get_thread_ids(mi_output *res, int **list)
755{
756 mi_results *vids, *lids;
757 int ids=-1, i;
758
759 *list=NULL;
760 vids=mi_get_var(res,"number-of-threads");
761 lids=mi_get_var(res,"thread-ids");
762 if (vids && vids->type==t_const &&
763 lids && lids->type==t_tuple)
764 {
765 ids=atoi(vids->v.cstr);
766 if (ids)
767 {
768 int *lst;
769 lst=(int *)mi_calloc(ids,sizeof(int));
770 if (lst)
771 {
772 lids=lids->v.rs;
773 i=0;
774 while (lids)
775 {
776 if (strcmp(lids->var,"thread-id")==0 && lids->type==t_const)
777 lst[i++]=atoi(lids->v.cstr);
778 lids=lids->next;
779 }
780 *list=lst;
781 }
782 else
783 ids=-1;
784 }
785 }
786 return ids;
787}
788
789int mi_res_thread_ids(mi_h *h, int **list)
790{
791 mi_output *r, *res;
792 int ids=-1;
793
794 r=mi_get_response_blk(h);
795 res=mi_get_rrecord(r);
796 if (res && res->tclass==MI_CL_DONE)
797 ids=mi_get_thread_ids(res,list);
798 mi_free_output(r);
799 return ids;
800}
801
802enum mi_gvar_lang mi_lang_str_to_enum(const char *lang)
803{
804 enum mi_gvar_lang lg=lg_unknown;
805
806 if (strcmp(lang,"C")==0)
807 lg=lg_c;
808 else if (strcmp(lang,"C++")==0)
809 lg=lg_cpp;
810 else if (strcmp(lang,"Java")==0)
811 lg=lg_java;
812
813 return lg;
814}
815
816const char *mi_lang_enum_to_str(enum mi_gvar_lang lang)
817{
818 const char *lg;
819
820 switch (lang)
821 {
822 case lg_c:
823 lg="C";
824 break;
825 case lg_cpp:
826 lg="C++";
827 break;
828 case lg_java:
829 lg="Java";
830 break;
831 /*case lg_unknown:*/
832 default:
833 lg="unknown";
834 break;
835 }
836 return lg;
837}
838
839enum mi_gvar_fmt mi_format_str_to_enum(const char *format)
840{
841 enum mi_gvar_fmt fmt=fm_natural;
842
843 if (strcmp(format,"binary")==0)
844 fmt=fm_binary;
845 else if (strcmp(format,"decimal")==0)
846 fmt=fm_decimal;
847 else if (strcmp(format,"hexadecimal")==0)
848 fmt=fm_hexadecimal;
849 else if (strcmp(format,"octal")==0)
850 fmt=fm_octal;
851
852 return fmt;
853}
854
855const char *mi_format_enum_to_str(enum mi_gvar_fmt format)
856{
857 const char *fmt;
858
859 switch (format)
860 {
861 case fm_natural:
862 fmt="natural";
863 break;
864 case fm_binary:
865 fmt="binary";
866 break;
867 case fm_decimal:
868 fmt="decimal";
869 break;
870 case fm_hexadecimal:
871 fmt="hexadecimal";
872 break;
873 case fm_octal:
874 fmt="octal";
875 break;
876 case fm_raw:
877 fmt="raw";
878 break;
879 default:
880 fmt="unknown";
881 }
882 return fmt;
883}
884
885char mi_format_enum_to_char(enum mi_gvar_fmt format)
886{
887 char fmt;
888
889 switch (format)
890 {
891 case fm_natural:
892 fmt='N';
893 break;
894 case fm_binary:
895 fmt='t';
896 break;
897 case fm_decimal:
898 fmt='d';
899 break;
900 case fm_hexadecimal:
901 fmt='x';
902 break;
903 case fm_octal:
904 fmt='o';
905 break;
906 case fm_raw:
907 fmt='r';
908 break;
909 default:
910 fmt=' ';
911 }
912 return fmt;
913}
914
915mi_gvar *mi_get_gvar(mi_output *o, mi_gvar *cur, const char *expression)
916{
917 mi_results *r;
918 mi_gvar *res=cur ? cur : mi_alloc_gvar();
919 int l;
920
921 if (!res)
922 return res;
923 r=o->c;
924 if (expression)
925 res->exp=strdup(expression);
926 while (r)
927 {
928 if (r->type==t_const)
929 {
930 if (strcmp(r->var,"name")==0)
931 {
932 free(res->name);
933 res->name=r->v.cstr;
934 r->v.cstr=NULL;
935 }
936 else if (strcmp(r->var,"numchild")==0)
937 {
938 res->numchild=atoi(r->v.cstr);
939 }
940 else if (strcmp(r->var,"type")==0)
941 {
942 free(res->type);
943 res->type=r->v.cstr;
944 r->v.cstr=NULL;
945 l=strlen(res->type);
946 if (l && res->type[l-1]=='*')
947 res->ispointer=1;
948 }
949 else if (strcmp(r->var,"lang")==0)
950 {
951 res->lang=mi_lang_str_to_enum(r->v.cstr);
952 }
953 else if (strcmp(r->var,"exp")==0)
954 {
955 free(res->exp);
956 res->exp=r->v.cstr;
957 r->v.cstr=NULL;
958 }
959 else if (strcmp(r->var,"format")==0)
960 {
961 res->format=mi_format_str_to_enum(r->v.cstr);
962 }
963 else if (strcmp(r->var,"attr")==0)
964 { /* Note: gdb 6.1.1 have only this: */
965 if (strcmp(r->v.cstr,"editable")==0)
966 res->attr=MI_ATTR_EDITABLE;
967 else /* noneditable */
968 res->attr=MI_ATTR_NONEDITABLE;
969 }
970 }
971 r=r->next;
972 }
973 return res;
974}
975
976mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression)
977{
978 mi_output *r, *res;
979 mi_gvar *gvar=NULL;
980
981 r=mi_get_response_blk(h);
982 res=mi_get_rrecord(r);
983 if (res && res->tclass==MI_CL_DONE)
984 gvar=mi_get_gvar(res,cur,expression);
985 mi_free_output(r);
986 return gvar;
987}
988
989mi_gvar_chg *mi_get_gvar_chg(mi_results *r)
990{
991 mi_gvar_chg *n;
992
993 if (r->type!=t_const)
994 return NULL;
995 n=mi_alloc_gvar_chg();
996 if (n)
997 {
998 while (r)
999 {
1000 if (r->type==t_const)
1001 {
1002 if (strcmp(r->var,"name")==0)
1003 {
1004 n->name=r->v.cstr;
1005 r->v.cstr=NULL;
1006 }
1007 else if (strcmp(r->var,"in_scope")==0)
1008 {
1009 n->in_scope=strcmp(r->v.cstr,"true")==0;
1010 }
1011 else if (strcmp(r->var,"new_type")==0)
1012 {
1013 n->new_type=r->v.cstr;
1014 r->v.cstr=NULL;
1015 }
1016 else if (strcmp(r->var,"new_num_children")==0)
1017 {
1018 n->new_num_children=atoi(r->v.cstr);
1019 }
1020 // type_changed="false" is the default
1021 }
1022 r=r->next;
1023 }
1024 }
1025 return n;
1026}
1027
1028int mi_res_changelist(mi_h *h, mi_gvar_chg **changed)
1029{
1030 mi_gvar_chg *last, *n;
1031 mi_results *res=mi_res_done_var(h,"changelist"), *r;
1032 int count=0;
1033
1034 *changed=NULL;
1035 if (!res)
1036 return 0;
1037 last=NULL;
1038 count=1;
1039 n=NULL;
1040 r=res->v.rs;
1041
1042 if (res->type==t_list)
1043 {// MI v2 a list of tuples
1044 while (r)
1045 {
1046 if (r->type==t_tuple)
1047 {
1048 n=mi_get_gvar_chg(r->v.rs);
1049 if (n)
1050 {
1051 if (last)
1052 last->next=n;
1053 else
1054 *changed=n;
1055 last=n;
1056 count++;
1057 }
1058 }
1059 r=r->next;
1060 }
1061 }
1062 else if (res->type==t_tuple)
1063 {// MI v1 a tuple with all together *8-P
1064 while (r)
1065 {
1066 if (r->type==t_const) /* Just in case. */
1067 {/* Get one var. */
1068 if (strcmp(r->var,"name")==0)
1069 {
1070 if (n)
1071 {/* Add to the list*/
1072 if (last)
1073 last->next=n;
1074 else
1075 *changed=n;
1076 last=n;
1077 count++;
1078 }
1079 n=mi_alloc_gvar_chg();
1080 if (!n)
1081 {
1082 mi_free_gvar_chg(*changed);
1083 return 0;
1084 }
1085 n->name=r->v.cstr;
1086 r->v.cstr=NULL;
1087 }
1088 else if ((NULL != n) && (strcmp(r->var,"in_scope")==0))
1089 {
1090 n->in_scope=strcmp(r->v.cstr,"true")==0;
1091 }
1092 else if ((NULL != n) && (strcmp(r->var,"new_type")==0))
1093 {
1094 n->new_type=r->v.cstr;
1095 r->v.cstr=NULL;
1096 }
1097 else if ((NULL != n) && (strcmp(r->var,"new_num_children")==0))
1098 {
1099 n->new_num_children=atoi(r->v.cstr);
1100 }
1101 // type_changed="false" is the default
1102 }
1103 r=r->next;
1104 }
1105 if (n)
1106 {/* Add to the list*/
1107 if (last)
1108 last->next=n;
1109 else
1110 *changed=n;
1111 last=n;
1112 count++;
1113 }
1114 }
1115 mi_free_results(res);
1116
1117 return count;
1118}
1119
1120int mi_get_children(mi_results *ch, mi_gvar *v)
1121{
1122 mi_gvar *cur=NULL, *aux;
1123 int i=0, count=v->numchild, l;
1124
1125 while (ch)
1126 {
1127 if (strcmp(ch->var,"child")==0 && ch->type==t_tuple && i<count)
1128 {
1129 mi_results *r=ch->v.rs;
1130 aux=mi_alloc_gvar();
1131 if (!aux)
1132 return 0;
1133 if (!v->child)
1134 v->child=aux;
1135 else if (NULL != cur)
1136 cur->next=aux;
1137 cur=aux;
1138 cur->parent=v;
1139 cur->depth=v->depth+1;
1140
1141 while (r)
1142 {
1143 if (r->type==t_const)
1144 {
1145 if (strcmp(r->var,"name")==0)
1146 {
1147 cur->name=r->v.cstr;
1148 r->v.cstr=NULL;
1149 }
1150 else if (strcmp(r->var,"exp")==0)
1151 {
1152 cur->exp=r->v.cstr;
1153 r->v.cstr=NULL;
1154 }
1155 else if (strcmp(r->var,"type")==0)
1156 {
1157 cur->type=r->v.cstr;
1158 r->v.cstr=NULL;
1159 l=strlen(cur->type);
1160 if (l && cur->type[l-1]=='*')
1161 cur->ispointer=1;
1162 }
1163 else if (strcmp(r->var,"value")==0)
1164 {
1165 cur->value=r->v.cstr;
1166 r->v.cstr=NULL;
1167 }
1168 else if (strcmp(r->var,"numchild")==0)
1169 {
1170 cur->numchild=atoi(r->v.cstr);
1171 }
1172 }
1173 r=r->next;
1174 }
1175 i++;
1176 }
1177 ch=ch->next;
1178 }
1179 v->vischild=i;
1180 v->opened=1;
1181 return i==v->numchild;
1182}
1183
1184int mi_res_children(mi_h *h, mi_gvar *v)
1185{
1186 mi_output *r, *res;
1187 int ok=0;
1188
1189 r=mi_get_response_blk(h);
1190 res=mi_get_rrecord(r);
1191 if (res && res->tclass==MI_CL_DONE)
1192 {
1193 mi_results *num=mi_get_var(res,"numchild");
1194 if (num && num->type==t_const)
1195 {
1196 v->numchild=atoi(num->v.cstr);
1197 if (v->child)
1198 {
1199 mi_free_gvar(v->child);
1200 v->child=NULL;
1201 }
1202 if (v->numchild)
1203 {
1204 mi_results *ch =mi_get_var(res,"children");
1205 if (ch && ch->type!=t_const) /* MI v1 tuple, MI v2 list */
1206 ok=mi_get_children(ch->v.rs,v);
1207 }
1208 else
1209 ok=1;
1210 }
1211 }
1212 mi_free_output(r);
1213 return ok;
1214}
1215
1216mi_bkpt *mi_get_bkpt(mi_results *p)
1217{
1218 mi_bkpt *res;
1219 char *end;
1220
1221 res=mi_alloc_bkpt();
1222 if (!res)
1223 return NULL;
1224 while (p)
1225 {
1226 if (p->type==t_const && p->var)
1227 {
1228 if (strcmp(p->var,"number")==0)
1229 res->number=atoi(p->v.cstr);
1230 else if (strcmp(p->var,"type")==0)
1231 {
1232 if (strcmp(p->v.cstr,"breakpoint")==0)
1233 res->type=t_breakpoint;
1234 else
1235 res->type=t_unknown;
1236 }
1237 else if (strcmp(p->var,"disp")==0)
1238 {
1239 if (strcmp(p->v.cstr,"keep")==0)
1240 res->disp=d_keep;
1241 else if (strcmp(p->v.cstr,"del")==0)
1242 res->disp=d_del;
1243 else
1244 res->disp=d_unknown;
1245 }
1246 else if (strcmp(p->var,"enabled")==0)
1247 res->enabled=p->v.cstr[0]=='y';
1248 else if (strcmp(p->var,"addr")==0)
1249 res->addr=(void *)strtoul(p->v.cstr,&end,0);
1250 else if (strcmp(p->var,"func")==0)
1251 {
1252 res->func=p->v.cstr;
1253 p->v.cstr=NULL;
1254 }
1255 else if (strcmp(p->var,"file")==0)
1256 {
1257 res->file=p->v.cstr;
1258 p->v.cstr=NULL;
1259 }
1260 else if (strcmp(p->var,"line")==0)
1261 res->line=atoi(p->v.cstr);
1262 else if (strcmp(p->var,"times")==0)
1263 res->times=atoi(p->v.cstr);
1264 else if (strcmp(p->var,"ignore")==0)
1265 res->ignore=atoi(p->v.cstr);
1266 else if (strcmp(p->var,"cond")==0)
1267 {
1268 res->cond=p->v.cstr;
1269 p->v.cstr=NULL;
1270 }
1271 }
1272 p=p->next;
1273 }
1274 return res;
1275}
1276
1277mi_bkpt *mi_res_bkpt(mi_h *h)
1278{
1279 mi_results *r=mi_res_done_var(h,"bkpt");
1280 mi_bkpt *b=NULL;
1281
1282 if (r && r->type==t_tuple)
1283 b=mi_get_bkpt(r->v.rs);
1284 mi_free_results(r);
1285 return b;
1286}
1287
1288mi_wp *mi_get_wp(mi_results *p, enum mi_wp_mode m)
1289{
1290 mi_wp *res=mi_alloc_wp();
1291
1292 if (res)
1293 {
1294 res->mode=m;
1295 while (p)
1296 {
1297 if (p->type==t_const && p->var)
1298 {
1299 if (strcmp(p->var,"number")==0)
1300 {
1301 res->number=atoi(p->v.cstr);
1302 res->enabled=1;
1303 }
1304 else if (strcmp(p->var,"exp")==0)
1305 {
1306 res->exp=p->v.cstr;
1307 p->v.cstr=NULL;
1308 }
1309 }
1310 p=p->next;
1311 }
1312 }
1313 return res;
1314}
1315
1316mi_wp *mi_parse_wp_res(mi_output *r)
1317{
1318 mi_results *p;
1319 enum mi_wp_mode m=wm_unknown;
1320
1321 /* The info is in a result wpt=... */
1322 p=r->c;
1323 while (p)
1324 {
1325 if (p->var)
1326 {
1327 if (strcmp(p->var,"wpt")==0)
1328 m=wm_write;
1329 else if (strcmp(p->var,"hw-rwpt")==0)
1330 m=wm_read;
1331 else if (strcmp(p->var,"hw-awpt")==0)
1332 m=wm_rw;
1333 if (m!=wm_unknown)
1334 break;
1335 }
1336 p=p->next;
1337 }
1338 if (!p || p->type!=t_tuple)
1339 return NULL;
1340 /* Scan the values inside it. */
1341 return mi_get_wp(p->v.rs,m);
1342}
1343
1344mi_wp *mi_res_wp(mi_h *h)
1345{
1346 mi_output *r, *res;
1347 mi_wp *ret=NULL;
1348
1349 r=mi_get_response_blk(h);
1350 res=mi_get_rrecord(r);
1351
1352 if (res)
1353 ret=mi_parse_wp_res(res);
1354
1355 mi_free_output(r);
1356 return ret;
1357}
1358
1359char *mi_res_value(mi_h *h)
1360{
1361 mi_results *r=mi_res_done_var(h,"value");
1362 char *s=NULL;
1363
1364 if (r && r->type==t_const)
1365 {
1366 s=r->v.cstr;
1367 r->v.rs=NULL;
1368 }
1369 mi_free_results(r);
1370 return s;
1371}
1372
1373mi_output *mi_get_stop_record(mi_output *r)
1374{
1375 while (r)
1376 {
1377 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
1378 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
1379 return r;
1380 r=r->next;
1381 }
1382 return r;
1383}
1384
1385static
1386char *reason_names[]=
1387{
1388 "breakpoint-hit",
1389 "watchpoint-trigger",
1390 "read-watchpoint-trigger",
1391 "access-watchpoint-trigger",
1392 "watchpoint-scope",
1393 "function-finished",
1394 "location-reached",
1395 "end-stepping-range",
1396 "exited-signalled",
1397 "exited",
1398 "exited-normally",
1399 "signal-received"
1400};
1401
1402static
1403enum mi_stop_reason reason_values[]=
1404{
1405 sr_bkpt_hit,
1406 sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
1407 sr_function_finished, sr_location_reached, sr_end_stepping_range,
1408 sr_exited_signalled, sr_exited, sr_exited_normally,
1409 sr_signal_received
1410};
1411
1412static
1413char *reason_expl[]=
1414{
1415 "Hit a breakpoint",
1416 "Write watchpoint",
1417 "Read watchpoint",
1418 "Access watchpoint",
1419 "Watchpoint out of scope",
1420 "Function finished",
1421 "Location reached",
1422 "End of stepping",
1423 "Exited signalled",
1424 "Exited with error",
1425 "Exited normally",
1426 "Signal received"
1427};
1428
1429enum mi_stop_reason mi_reason_str_to_enum(const char *s)
1430{
1431 int i;
1432
1433 for (i=0; i<sizeof(reason_names)/sizeof(char *); i++)
1434 if (strcmp(reason_names[i],s)==0)
1435 return reason_values[i];
1436 return sr_unknown;
1437}
1438
1439const char *mi_reason_enum_to_str(enum mi_stop_reason r)
1440{
1441 int i;
1442
1443 if (r==sr_unknown)
1444 return "Unknown (temp bkp?)";
1445 for (i=0; i<sizeof(reason_values)/sizeof(char *); i++)
1446 if (reason_values[i]==r)
1447 return reason_expl[i];
1448 return NULL;
1449}
1450
1451mi_stop *mi_get_stopped(mi_results *r)
1452{
1453 mi_stop *res=mi_alloc_stop();
1454
1455 if (res)
1456 {
1457 while (r)
1458 {
1459 if (r->type==t_const)
1460 {
1461 if (strcmp(r->var,"reason")==0)
1462 res->reason=mi_reason_str_to_enum(r->v.cstr);
1463 else if (!res->have_thread_id && strcmp(r->var,"thread-id")==0)
1464 {
1465 res->have_thread_id=1;
1466 res->thread_id=atoi(r->v.cstr);
1467 }
1468 else if (!res->have_bkptno && strcmp(r->var,"bkptno")==0)
1469 {
1470 res->have_bkptno=1;
1471 res->bkptno=atoi(r->v.cstr);
1472 }
1473 else if (!res->have_bkptno && strcmp(r->var,"wpnum")==0)
1474 {
1475 res->have_wpno=1;
1476 res->wpno=atoi(r->v.cstr);
1477 }
1478 else if (strcmp(r->var,"gdb-result-var")==0)
1479 {
1480 res->gdb_result_var=r->v.cstr;
1481 r->v.cstr=NULL;
1482 }
1483 else if (strcmp(r->var,"return-value")==0)
1484 {
1485 res->return_value=r->v.cstr;
1486 r->v.cstr=NULL;
1487 }
1488 else if (strcmp(r->var,"signal-name")==0)
1489 {
1490 res->signal_name=r->v.cstr;
1491 r->v.cstr=NULL;
1492 }
1493 else if (strcmp(r->var,"signal-meaning")==0)
1494 {
1495 res->signal_meaning=r->v.cstr;
1496 r->v.cstr=NULL;
1497 }
1498 else if (!res->have_exit_code && strcmp(r->var,"exit-code")==0)
1499 {
1500 res->have_exit_code=1;
1501 res->exit_code=atoi(r->v.cstr);
1502 }
1503 }
1504 else // tuple or list
1505 {
1506 if (strcmp(r->var,"frame")==0)
1507 res->frame=mi_parse_frame(r->v.rs);
1508 else if (!res->wp && strcmp(r->var,"wpt")==0)
1509 res->wp=mi_get_wp(r->v.rs,wm_write);
1510 else if (!res->wp && strcmp(r->var,"hw-rwpt")==0)
1511 res->wp=mi_get_wp(r->v.rs,wm_read);
1512 else if (!res->wp && strcmp(r->var,"hw-awpt")==0)
1513 res->wp=mi_get_wp(r->v.rs,wm_rw);
1514 else if (!(res->wp_old || res->wp_val) && strcmp(r->var,"value")==0)
1515 {
1516 mi_results *p=r->v.rs;
1517 while (p)
1518 {
1519 if (strcmp(p->var,"value")==0 || strcmp(p->var,"new")==0)
1520 {
1521 res->wp_val=p->v.cstr;
1522 p->v.cstr=NULL;
1523 }
1524 else if (strcmp(p->var,"old")==0)
1525 {
1526 res->wp_old=p->v.cstr;
1527 p->v.cstr=NULL;
1528 }
1529 p=p->next;
1530 }
1531 }
1532 }
1533 r=r->next;
1534 }
1535 }
1536 return res;
1537}
1538
1539mi_stop *mi_res_stop(mi_h *h)
1540{
1541 mi_output *o=mi_retire_response(h);
1542 mi_stop *stop=NULL;
1543
1544 if (o)
1545 {
1546 mi_output *sr=mi_get_stop_record(o);
1547 if (sr)
1548 stop=mi_get_stopped(sr->c);
1549 }
1550 mi_free_output(o);
1551
1552 return stop;
1553}
1554
1555int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
1556 unsigned long *addr)
1557{
1558 char *end;
1559 mi_results *res=mi_res_done_var(h,"memory"), *r;
1560 int ok=0;
1561
1562 *na=0;
1563 r=res;
1564 if (r && r->type==t_list && ws==1)
1565 {
1566 r=r->v.rs;
1567 if (r->type!=t_tuple)
1568 {
1569 mi_free_results(res);
1570 return 0;
1571 }
1572 r=r->v.rs;
1573 while (r)
1574 {
1575 if (r->type==t_list && strcmp(r->var,"data")==0)
1576 {
1577 mi_results *data=r->v.rs;
1578 ok++;
1579 if (data && data->type==t_const &&
1580 strcmp(data->v.cstr,"N/A")==0)
1581 *na=1;
1582 else
1583 while (data)
1584 {
1585 if (data->type==t_const)
1586 *(dest++)=strtol(data->v.cstr,&end,0);
1587 data=data->next;
1588 }
1589 }
1590 else if (r->type==t_const && strcmp(r->var,"addr")==0)
1591 {
1592 ok++;
1593 if (addr)
1594 *addr=strtoul(r->v.cstr,&end,0);
1595 }
1596 r=r->next;
1597 }
1598
1599 }
1600 mi_free_results(res);
1601 return ok==2;
1602}
1603
1604mi_asm_insn *mi_parse_insn(mi_results *c)
1605{
1606 mi_asm_insn *res=NULL, *cur=NULL;
1607 mi_results *sub;
1608 char *end;
1609
1610 while (c)
1611 {
1612 if (c->type==t_tuple)
1613 {
1614 if (!res)
1615 res=cur=mi_alloc_asm_insn();
1616 else
1617 {
1618 cur->next=mi_alloc_asm_insn();
1619 cur=cur->next;
1620 }
1621 if (!cur)
1622 {
1623 mi_free_asm_insn(res);
1624 return NULL;
1625 }
1626 sub=c->v.rs;
1627 while (sub)
1628 {
1629 if (sub->type==t_const)
1630 {
1631 if (strcmp(sub->var,"address")==0)
1632 cur->addr=(void *)strtoul(sub->v.cstr,&end,0);
1633 else if (strcmp(sub->var,"func-name")==0)
1634 {
1635 cur->func=sub->v.cstr;
1636 sub->v.cstr=NULL;
1637 }
1638 else if (strcmp(sub->var,"offset")==0)
1639 cur->offset=atoi(sub->v.cstr);
1640 else if (strcmp(sub->var,"inst")==0)
1641 {
1642 cur->inst=sub->v.cstr;
1643 sub->v.cstr=NULL;
1644 }
1645 }
1646 sub=sub->next;
1647 }
1648 }
1649 c=c->next;
1650 }
1651 return res;
1652}
1653
1654mi_asm_insns *mi_parse_insns(mi_results *c)
1655{
1656 mi_asm_insns *res=NULL, *cur=NULL;
1657 mi_results *sub;
1658
1659 while (c)
1660 {
1661 if (c->var)
1662 {
1663 if (strcmp(c->var,"src_and_asm_line")==0 && c->type==t_tuple)
1664 {
1665 if (!res)
1666 res=cur=mi_alloc_asm_insns();
1667 else
1668 {
1669 cur->next=mi_alloc_asm_insns();
1670 cur=cur->next;
1671 }
1672 if (!cur)
1673 {
1674 mi_free_asm_insns(res);
1675 return NULL;
1676 }
1677 sub=c->v.rs;
1678 while (sub)
1679 {
1680 if (sub->var)
1681 {
1682 if (sub->type==t_const)
1683 {
1684 if (strcmp(sub->var,"line")==0)
1685 cur->line=atoi(sub->v.cstr);
1686 else if (strcmp(sub->var,"file")==0)
1687 {
1688 cur->file=sub->v.cstr;
1689 sub->v.cstr=NULL;
1690 }
1691 }
1692 else if (sub->type==t_list)
1693 {
1694 if (strcmp(sub->var,"line_asm_insn")==0)
1695 cur->ins=mi_parse_insn(sub->v.rs);
1696 }
1697 }
1698 sub=sub->next;
1699 }
1700 }
1701 }
1702 else
1703 {/* No source line, just instructions */
1704 res=mi_alloc_asm_insns();
1705 res->ins=mi_parse_insn(c);
1706 break;
1707 }
1708 c=c->next;
1709 }
1710 return res;
1711}
1712
1713
1714mi_asm_insns *mi_get_asm_insns(mi_h *h)
1715{
1716 mi_results *r=mi_res_done_var(h,"asm_insns");
1717 mi_asm_insns *f=NULL;
1718
1719 if (r && r->type==t_list)
1720 f=mi_parse_insns(r->v.rs);
1721 mi_free_results(r);
1722 return f;
1723}
1724
1725mi_chg_reg *mi_parse_list_regs(mi_results *r, int *how_many)
1726{
1727 mi_results *c=r;
1728 int cregs=0;
1729 mi_chg_reg *first=NULL, *cur=NULL;
1730
1731 /* Create the list. */
1732 while (c)
1733 {
1734 if (c->type==t_const && !c->var)
1735 {
1736 if (first)
1737 cur=cur->next=mi_alloc_chg_reg();
1738 else
1739 first=cur=mi_alloc_chg_reg();
1740
1741 if (NULL != cur) {
1742 cur->name=c->v.cstr;
1743 cur->reg=cregs++;
1744 c->v.cstr=NULL;
1745 }
1746 }
1747 c=c->next;
1748 }
1749 if (how_many)
1750 *how_many=cregs;
1751
1752 return first;
1753}
1754
1755mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many)
1756{
1757 mi_results *r=mi_res_done_var(h,"register-names");
1758 mi_chg_reg *l=NULL;
1759
1760 if (r && r->type==t_list)
1761 l=mi_parse_list_regs(r->v.rs,how_many);
1762 mi_free_results(r);
1763 return l;
1764}
1765
1766mi_chg_reg *mi_parse_list_changed_regs(mi_results *r)
1767{
1768 mi_results *c=r;
1769 mi_chg_reg *first=NULL, *cur=NULL;
1770
1771 /* Create the list. */
1772 while (c)
1773 {
1774 if (c->type==t_const && !c->var)
1775 {
1776 if (first)
1777 cur=cur->next=mi_alloc_chg_reg();
1778 else
1779 first=cur=mi_alloc_chg_reg();
1780 cur->reg=atoi(c->v.cstr);
1781 }
1782 c=c->next;
1783 }
1784
1785 return first;
1786}
1787
1788mi_chg_reg *mi_get_list_changed_regs(mi_h *h)
1789{
1790 mi_results *r=mi_res_done_var(h,"changed-registers");
1791 mi_chg_reg *changed=NULL;
1792
1793 if (r && r->type==t_list)
1794 changed=mi_parse_list_changed_regs(r->v.rs);
1795 mi_free_results(r);
1796 return changed;
1797}
1798
1799int mi_parse_reg_values(mi_results *r, mi_chg_reg *l)
1800{
1801 mi_results *c;
1802
1803 while (r && l)
1804 {
1805 if (r->type==t_tuple && !r->var)
1806 {
1807 c=r->v.rs;
1808 while (c)
1809 {
1810 if (c->type==t_const && c->var)
1811 {
1812 if (strcmp(c->var,"number")==0)
1813 {
1814 if (atoi(c->v.cstr)!=l->reg)
1815 {
1816 mi_error=MI_PARSER;
1817 return 0;
1818 }
1819 }
1820 else if (strcmp(c->var,"value")==0)
1821 {
1822 l->val=c->v.cstr;
1823 c->v.cstr=NULL;
1824 }
1825 }
1826 c=c->next;
1827 }
1828 }
1829 r=r->next;
1830 l=l->next;
1831 }
1832
1833 return !l && !r;
1834}
1835
1836int mi_get_reg_values(mi_h *h, mi_chg_reg *l)
1837{
1838 mi_results *r=mi_res_done_var(h,"register-values");
1839 int ok=0;
1840
1841 if (r && r->type==t_list)
1842 ok=mi_parse_reg_values(r->v.rs,l);
1843 mi_free_results(r);
1844 return ok;
1845}
1846
1847int mi_parse_list_regs_l(mi_results *r, mi_chg_reg *l)
1848{
1849 while (r && l)
1850 {
1851 if (r->type==t_const && !r->var)
1852 {
1853 free(l->name);
1854 l->name=r->v.cstr;
1855 r->v.cstr=NULL;
1856 l=l->next;
1857 }
1858 r=r->next;
1859 }
1860
1861 return !l && !r;
1862}
1863
1864int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l)
1865{
1866 mi_results *r=mi_res_done_var(h,"register-names");
1867 int ok=0;
1868
1869 if (r && r->type==t_list)
1870 ok=mi_parse_list_regs_l(r->v.rs,l);
1871 mi_free_results(r);
1872 return ok;
1873}
1874
1875mi_chg_reg *mi_parse_reg_values_l(mi_results *r, int *how_many)
1876{
1877 mi_results *c;
1878 mi_chg_reg *first=NULL, *cur=NULL;
1879 *how_many=0;
1880
1881 while (r)
1882 {
1883 if (r->type==t_tuple && !r->var)
1884 {
1885 c=r->v.rs;
1886 if (first)
1887 cur=cur->next=mi_alloc_chg_reg();
1888 else
1889 first=cur=mi_alloc_chg_reg();
1890 while (c)
1891 {
1892 if (c->type==t_const && c->var)
1893 {
1894 if (strcmp(c->var,"number")==0)
1895 {
1896 if (NULL != cur)
1897 cur->reg=atoi(c->v.cstr);
1898 (*how_many)++;
1899 }
1900 else if (strcmp(c->var,"value")==0)
1901 {
1902 if (NULL != cur)
1903 cur->val=c->v.cstr;
1904 c->v.cstr=NULL;
1905 }
1906 }
1907 c=c->next;
1908 }
1909 }
1910 r=r->next;
1911 }
1912
1913 return first;
1914}
1915
1916mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many)
1917{
1918 mi_results *r=mi_res_done_var(h,"register-values");
1919 mi_chg_reg *rgs=NULL;
1920
1921 if (r && r->type==t_list)
1922 rgs=mi_parse_reg_values_l(r->v.rs,how_many);
1923 mi_free_results(r);
1924 return rgs;
1925}
1926
1927