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