"Fossies" - the Fresh Open Source Software Archive 
Member "xxgdb-1.12/gdb_parser.c" (22 Nov 1994, 37855 Bytes) of package /linux/misc/old/xxgdb-1.12.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*****************************************************************************
2 *
3 * xdbx - X Window System interface to the dbx debugger
4 *
5 * Copyright 1989 The University of Texas at Austin
6 * Copyright 1990 Microelectronics and Computer Technology Corporation
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted,
10 * provided that the above copyright notice appear in all copies and that
11 * both that copyright notice and this permission notice appear in
12 * supporting documentation, and that the name of The University of Texas
13 * and Microelectronics and Computer Technology Corporation (MCC) not be
14 * used in advertising or publicity pertaining to distribution of
15 * the software without specific, written prior permission. The
16 * University of Texas and MCC makes no representations about the
17 * suitability of this software for any purpose. It is provided "as is"
18 * without express or implied warranty.
19 *
20 * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
21 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
23 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
24 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
25 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 *
28 * Author: Po Cheung
29 * Created: March 10, 1989
30 *
31 *****************************************************************************
32 *
33 * xxgdb - X Window System interface to the gdb debugger
34 *
35 * Copyright 1990,1993 Thomson Consumer Electronics, Inc.
36 *
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted,
39 * provided that the above copyright notice appear in all copies and that
40 * both that copyright notice and this permission notice appear in
41 * supporting documentation, and that the name of Thomson Consumer
42 * Electronics (TCE) not be used in advertising or publicity pertaining
43 * to distribution of the software without specific, written prior
44 * permission. TCE makes no representations about the suitability of
45 * this software for any purpose. It is provided "as is" without express
46 * or implied warranty.
47 *
48 * TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
49 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
50 * SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
51 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
52 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
53 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 * SOFTWARE.
55 *
56 * Adaptation to GDB: Pierre Willard
57 * XXGDB Created: December, 1990
58 *
59 *****************************************************************************/
60
61 /* gdb_parser.c:
62 *
63 * WARNING : gdb_parser.c is included by parser.c for GDB.
64 *
65 * Parse output messages from dbx using regular expression pattern matching,
66 * and take appropriate action.
67 *
68 * parse(): Parse the dbx output and invoke the appropriate action
69 * handler.
70 * filter(): Modify the dbx output before it gets displayed on the
71 * dialog window.
72 * gdb_source_command(): Test for source command.
73 */
74
75 /*
76 * iand 94/02/10 cope better with non-blocking I/O. Exit when pty is closed rather
77 * than spinning in a loop.
78 *
79 */
80
81 #include <string.h>
82 #include <stdio.h>
83 #include <errno.h>
84
85 extern Boolean Prompt; /* True when gdb prompt arrives */
86
87 /*--------------------------------------------------------------------------+
88 | |
89 | Function to output a message and ring bell when a answer |
90 | from gdb has not been recognized (possibly because of bug |
91 | in xxgdb which does not anticipate this particular answer). |
92 | |
93 | ECHO_ON means that all the output from gdb was displayed |
94 | on the dialog window (so no need to display any error message). |
95 | In particular we can arrive here because the user typed a |
96 | wrong command. |
97 | |
98 | ECHO_OFF means that the gdb command was issued internally by |
99 | xxgdb, and that the user has no knowledge of it. |
100 | |
101 | ECHO_ON and FILTER_ON means that only part of the |
102 | gdb answer to the command is displayed in the dialog window. |
103 | What is displayed or not is chosen by the filter() function. |
104 | In fact, filter() in this case will display gdb error messages |
105 | from the command sent internally by xxgdb. |
106 | |
107 | This function will only display error messages when echo and |
108 | filter are off. This is more for xxgdb debug than for the user. |
109 | |
110 +--------------------------------------------------------------------------*/
111 void unknown_output (outputstr, command, flags)
112 char *outputstr;
113 char *command;
114 int flags;
115 {
116 if (command)
117 {
118 if (debug)
119 fprintf(stderr, "\noutput from \"%s\" is not recognized\n", command);
120
121 /* if the command was completely silent, we output this
122 error message */
123
124 if ((flags & (ECHO_ON | FILTER_ON)) == 0)
125 {
126 AppendDialogText("xxgdb error: output from \"");
127 AppendDialogText(command);
128 AppendDialogText("\" command is not recognized.\n");
129 }
130 }
131
132 if (outputstr)
133 if ((flags & (ECHO_ON | FILTER_ON)) == 0)
134 AppendDialogText(outputstr);
135
136 bell(0); /* ring the bell in ALL cases */
137 }
138
139 /*--------------------------------------------------------------------------+
140 | |
141 | Function to remove all 'Reading in symbols' message |
142 | from a string. |
143 | |
144 | This function is used in parser() before matching the output |
145 | because this message can happen any time. |
146 | |
147 +--------------------------------------------------------------------------*/
148 void filter_reading_symbols(output)
149 char *output;
150 {
151 struct re_registers regs;
152 int r;
153 char *p1;
154 char *p2;
155
156 /* test for reading symbols message */
157
158 while (re_match(output_pattern[O_READING_SYMBOLS].buf,output,strlen(output),0,®s) > 0)
159 {
160 /* we found a "Reading in symbols for ...done." pattern */
161
162 r = output_pattern[O_READING_SYMBOLS].reg_token[TK_MESG];
163 p1= output+regs.start[r];
164 p2 = output+regs.end[r];
165
166 /* remove "Reading in symbols for ...done." */
167
168 while((*(p1++) = *(p2++)));
169 }
170 }
171
172 /*--------------------------------------------------------------------------+
173 | |
174 | * This routine first parses the command string. |
175 | * If the command is one of run, cont, next, step, stop at, stop in, |
176 | * where, up, or down, it parses the dbx output to decide what action |
177 | * to take and dispatch it to one of the handlers. |
178 | * For other commands, the appropriate handler is called. |
179 | * |
180 | * !!! This routine has to be re-entrant. |
181 | * |
182 +--------------------------------------------------------------------------*/
183 void parse(output, command, flags)
184 char *output;
185 char *command;
186 int flags;
187 {
188 int command_type;
189 char *output_string;
190
191 if (debug) {
192 char *temp;
193 if(!command)temp="";else temp=command;
194 fprintf(stderr, "parse(output = %s, command = %s, flags = %d)\n", output, temp, flags);
195 }
196
197 /* Make a local copy of `output' and use that instead */
198 output_string = XtNewString(output);
199 if (output) strcpy(output, "");
200
201 /* test for GDB start-up */
202
203 if (!command) {
204 /* (PW)28AUG91 : do no test for O_DEBUG pattern because of gdb 4.0
205 who most of the times displays nothing before the promt.
206 if (match(output_pattern, output_string, O_DEBUG) != -1)
207 */
208 {
209 query_gdb_directories(); /* will tell if running gdb 4.0 */
210
211 debug_handler(); /* some init to gdb, and try to display main() */
212
213 /* test if a core file was used in input arguments,
214 an display bomb if necessary. */
215
216 if (match(output_pattern, output_string, O_CORE_FILE) != -1)
217 core_file_handler();
218 }
219 debug_init(); /* read .gdbinit file (if any) */
220 XtFree(output_string);
221 return;
222 }
223
224 /* if not GDB start-up */
225
226 if (match(output_pattern, output_string, O_BELL) != -1)
227 {
228 /* test if this is 'show undefined'. If yes then we are
229 not executing the new gdb (4.0).
230 (see show_is_undefined in gdb_handler.c)
231 */
232 if (match(output_pattern, output_string, O_UNDEF_SHOW) != -1)
233 show_is_undefined();
234 else
235 unknown_output (output_string,command, flags);
236 XtFree(output_string);
237 return;
238 }
239
240 command_type = match(command_pattern, command, C_ANY);
241
242 /* remove all "Reading in symbols for pw.c...done." */
243
244 filter_reading_symbols(output_string);
245
246 switch (command_type) {
247 case C_EXEC:
248 case C_FINISH:
249 {
250 char * message;
251 int signal = 0;
252 if (debug) {
253 fprintf(stderr, "C_EXEC or C_FINISH\n");
254 }
255 message = 0;
256 if (match(output_pattern, output_string, O_RECEIVED_SIGNAL) != -1)
257 {
258 message = XtNewString(Token.mesg);
259 signal = Token.stop; /* signal number received */
260 }
261
262 /* warning : the order of the matching tests is important */
263
264 if ((match(output_pattern, output_string, O_EXEC_MESS_AFTER) != -1)
265 || (match(output_pattern, output_string, O_EXEC_MESS_BEFORE) != -1)
266 || (match(output_pattern, output_string, O_EXEC_GDB) != -1))
267 {
268 exec_handler(message,signal);
269 }
270 else
271 {
272 if (match(output_pattern, output_string, O_DONE) != -1)
273 done_handler(message,signal);
274 else
275 unknown_output(output_string, command, flags);
276 }
277
278 if (message)
279 {
280 bell(0);
281 XtFree(message);
282 }
283 }
284 break;
285
286 case C_UPDOWN:
287 if (debug) {
288 fprintf(stderr, "C_UPDOWN\n");
289 }
290 if (match(output_pattern, output_string, O_UPDOWN) != -1)
291 updown_handler();
292 else if (match(output_pattern, output_string, O_UPDOWN_NOSOURCE) != -1)
293 /* here Token.msg and Token.func are updated. Do nothing with
294 them. We are in a function with no source information. */
295 bell(0);
296 else
297 unknown_output (output_string, command, flags);
298 break;
299 case C_SEARCH:
300 if (debug) {
301 fprintf(stderr, "C_SEARCH\n");
302 }
303 if (match(output_pattern, output_string, O_SEARCH) != -1)
304 search_handler();
305 else
306 unknown_output(output_string, command, flags);
307 break;
308 case C_DELETE:
309 if (debug) {
310 fprintf(stderr, "C_DELETE\n");
311 }
312 delete_handler();
313 break;
314 case C_LIST:
315 if (debug) {
316 fprintf(stderr, "C_LIST\n");
317 }
318 if (match(output_pattern, output_string, O_LIST) != -1)
319 list_handler();
320 else
321 unknown_output(output_string, command, flags);
322 break;
323
324 case C_BREAK:
325 if (debug) {
326 fprintf(stderr, "C_BREAK\n");
327 }
328 if (match(output_pattern, output_string, O_BREAK) != -1)
329 break_handler();
330 else
331 unknown_output(output_string, command, flags);
332 break;
333
334 case C_INFO_DIR:
335 if (debug) {
336 fprintf(stderr, "C_INFO_DIR\n");
337 }
338 if (match(output_pattern, output_string, O_INFO_DIR) != -1)
339 info_dir_handler();
340 else
341 unknown_output(output_string, command, flags);
342 break;
343
344 case C_DIRECTORY:
345 if (debug) {
346 fprintf(stderr, "C_DIRECTORY\n");
347 }
348 directory_handler();
349 break;
350
351 case C_INFO_LINE:
352 if (debug) {
353 fprintf(stderr, "C_INFO_LINE\n");
354 }
355 if (match(output_pattern, output_string, O_INFO_LINE) != -1)
356 info_line_handler(); /* command was 'info line' */
357 else
358 unknown_output(output_string, command, flags);
359 break;
360
361 case C_INFO_BREAK:
362 if (debug) {
363 fprintf(stderr, "C_INFO_BREAK\n");
364 }
365 info_break_handler(output_string);
366 break;
367
368 case C_DISPLAY: /* means "display foo\n" command */
369 if (debug) {
370 fprintf(stderr, "C_DISPLAY\n");
371 }
372 {
373 if ((strcmp(output_string, "") == 0) ||
374 (match(output_pattern, output_string, O_DISPLAY) != -1))
375 display_handler();
376 else
377 unknown_output(output_string, command, flags);
378 }
379 break;
380
381 case C_UNDISPLAY:
382 if (debug) {
383 fprintf(stderr, "C_UNDISPLAY\n");
384 }
385 if (strcmp(output_string, "") == 0)
386 display_handler();
387 else
388 unknown_output(output_string, command, flags);
389 break;
390
391 case C_DISPLAY_INFO: /* means "display\n" command */
392 if (debug) {
393 fprintf(stderr, "C_DISPLAY_INFO\n");
394 }
395 {
396 if ((strcmp(output_string, "") == 0) ||
397 (match(output_pattern, output_string, O_DISPLAY_INFO) != -1))
398 display_info_handler();
399 else
400 unknown_output(output_string, command, flags);
401 }
402 break;
403
404 case C_CD:
405 if (debug) {
406 fprintf(stderr, "C_CD\n");
407 }
408 if (new_gdb4()) /* this fixes where cd and pwd dont work right for 4.x
409 (cd doesn't do anything but beep, pwd doesn't work
410 when cwd is not cannonical) */
411 query_gdb ("pwd\n", PARSE_ON);
412 else if (match(output_pattern, output_string, O_CD) != -1)
413 cd_handler(Token.mesg);
414 else
415 unknown_output(output_string, command, flags);
416 break;
417
418 case C_PWD:
419 if (debug) {
420 fprintf(stderr, "C_PWD\n");
421 }
422 if (match(output_pattern, output_string, O_PWD) != -1)
423 pwd_handler(Token.display? Token.display : Token.mesg);
424 else
425 unknown_output(output_string, command, flags);
426 break;
427
428 case C_FRAME_CURR:
429 if (debug) {
430 fprintf(stderr, "C_FRAME_CURR\n");
431 }
432 if (match(output_pattern, output_string, O_FRAME_CURR) != -1)
433 frame_curr_handler();
434 else
435 unknown_output(output_string, command, flags);
436 break;
437
438 case C_PRINT:
439 if (debug) {
440 fprintf(stderr, "C_PRINT\n");
441 }
442 {
443 /* for GDB, the label of the popup display is the expression
444 string which is printed instead of $n */
445 char * prtname;
446 prtname = 0;
447 if ((Token.mesg) && (PopupMode))
448 prtname = XtNewString(Token.mesg);
449
450 if (match(output_pattern, output_string, O_PRINT) != -1)
451 {
452 if (prtname)
453 {
454 XtFree(Token.mesg);
455 Token.mesg = prtname;
456 prtname = 0; /* not to XtFree twice this string */
457 }
458 print_handler(output_string);
459 }
460 else
461 unknown_output(output_string, command, flags);
462
463 /* if PopupMode was true but GDB found an error in print
464 statement (ie match() returned -1), PopupMode was never reset */
465 PopupMode = FALSE;
466
467 XtFree(prtname);
468 }
469 break;
470
471 case C_SYMBOL_FILE:
472 case C_FILE:
473 if (debug) {
474 fprintf(stderr, "C_FILE or C_SYMBOL_FILE\n");
475 }
476 debug_handler();
477 break;
478
479 case C_SOURCE: /* WE SHOULD NEVER ARRIVE HERE */
480 if (debug) {
481 fprintf(stderr, "C_SOURCE - WE SHOULD NEVER ARRIVE HERE\n");
482 }
483 break;
484
485 case C_EXEC_FILE:
486 if (debug) {
487 fprintf(stderr, "C_EXEC_FILE\n");
488 }
489 break;
490
491 case C_CORE_FILE:
492 if (debug) {
493 fprintf(stderr, "C_CORE_FILE\n");
494 }
495 if (match(output_pattern, output_string, O_CORE_FILE) != -1)
496 core_file_handler();
497 else
498 unknown_output(output_string, command, flags);
499 break;
500
501 /* in case of 'info source', we do not call unknown_output()
502 if the pattern is not matched, because we only test for the
503 'compilation directory' line. When there is no compilation
504 directory, there is no match and there is no error...
505
506 (PW)8JUN93 : we also test for current source and current
507 source full pathname.
508 */
509
510 case C_INFO_SOURCE:
511 if (debug) {
512 fprintf(stderr, "C_INFO_SOURCE\n");
513 }
514 cdir[0] = 0;
515 source_fullpath[0] = 0;
516 source_path[0] = 0;
517 if (match(output_pattern, output_string, O_INFO_SOURCE) != -1)
518 info_source_handler(Token.mesg, Token.file, Token.func);
519 break;
520
521 default:
522 if (debug) {
523 fprintf(stderr, "C UNKNOWN\n");
524 }
525 break;
526 }
527 XtFree(output_string);
528 }
529
530 #ifdef NEED_STRSTR
531 /*--------------------------------------------------------------------------+
532 | |
533 | Some systems DO NOT have the ANSI strstr function |
534 | |
535 +--------------------------------------------------------------------------*/
536 char *
537 strstr (source, substr)
538 char *source;
539 char *substr;
540 {
541 char *src;
542 char *sub;
543
544 if (!source || !substr)
545 return NULL;
546
547 while (*source)
548 {
549 for (src = source, sub = substr;
550 (*src) && (*sub) && (*src == *sub);
551 src++,sub++);
552 if (!*sub)
553 return source;
554
555 source++;
556 }
557
558 return NULL;
559 }
560 #endif
561
562 /*--------------------------------------------------------------------------+
563 | |
564 | Function to filter all the display information in a string |
565 | |
566 | input : string pointer, |
567 | already_taken_care is number of char in string already |
568 | processed (eg, displayed). |
569 | |
570 | output : none. |
571 | |
572 | See O_EXEC_DISPLAY in gdb_regex.h for the display pattern. |
573 | |
574 | Take care when GDB send some message after '\032\032...\n' |
575 | which is not a display line. |
576 | |
577 | (gdb) finish |
578 | Run till exit from #0 foo (n=1) (pw.c line 9) |
579 | main () (pw.c line 41) |
580 | /usr1/gnu_sun4/xxgdb/pw.c:41:590:beg:0x232c |
581 | 1: i = 1 |
582 | Value returned is $1 = 1 |
583 | (gdb) |
584 | |
585 +--------------------------------------------------------------------------*/
586 void filter_display_info(output, already_taken_care)
587 char *output;
588 unsigned int already_taken_care;
589 {
590 struct re_registers regs;
591 int r;
592 char *p;
593 char *p1;
594 char *p2;
595 char *cp_output;
596 int begin_struct;
597
598 p = cp_output = XtNewString(output);
599
600 p1 = strstr(p,"\032\032"); /* find beginning of special gdb line */
601
602 if ((p1 == 0) || ((p2 = strchr(p1+1,'\n')) == 0))
603 {
604 AppendDialogText(p + already_taken_care); /* something wrong here */
605 XtFree(cp_output);
606 return;
607 }
608
609 *p1 = 0;
610
611 if (p1 > (p + already_taken_care)) {
612 AppendDialogText(p + already_taken_care); /* print everything before that line */
613 }
614 p = p2 + 1; /* end of that line + skip \n */
615
616 /* test for beginning of a display */
617
618 while (re_match(output_pattern[O_EXEC_DISPLAY].buf,p,strlen(p),0,®s) > 0)
619 {
620 /* we found a "X:....\n" pattern */
621
622 r = output_pattern[O_EXEC_DISPLAY].reg_token[TK_DISP];
623 p1= p+regs.start[r];
624 p2 = p+regs.end[r];
625
626 /* count number of { and } : if not equal, the next lines are part of this display */
627 begin_struct = 0;
628 while (p1 < p2)
629 {
630 switch(*(p1++))
631 {
632 case '{':
633 begin_struct++;
634 break;
635 case '}':
636 begin_struct--;
637 break;
638 }
639 }
640
641 p1=p+regs.start[r];
642 *p1 = 0;
643 if (p != p1) {
644 /* do not print anything already printed */
645 if (p < (cp_output + already_taken_care)) {
646 p = cp_output + already_taken_care;
647 }
648 if (p < p1) {
649 AppendDialogText(p); /* print what is before display */
650 }
651 }
652 p = p2; /* skip display text */
653
654 if (begin_struct) /* skip the whole data displayed */
655 {
656 do /* find the last '}' */
657 {
658 switch(*(p++))
659 {
660 case '{':
661 begin_struct++;
662 break;
663 case '}':
664 begin_struct--;
665 break;
666 }
667 }
668 while (begin_struct);
669
670 /* now skip until end of line */
671 while (*(p++) != '\n');
672 }
673 }
674
675 if (p < (cp_output + already_taken_care)) {
676 p = cp_output + already_taken_care; /* do not print anything already printed */
677 }
678 AppendDialogText(p); /* print what is after display */
679 XtFree(cp_output);
680 }
681
682 /*--------------------------------------------------------------------------+
683 | |
684 | * This function edits the dbx output so that unnecessary information is |
685 | * not displayed on the dialog window. |
686 | * It filters away the some output returned by the execution commands; |
687 | * output from the search commands, and the display command. |
688 | * On Sun dbx, it also filters away part of the output returned by the |
689 | * up and down commands. |
690 | * |
691 +--------------------------------------------------------------------------*/
692 void
693 filter (string, output, command)
694 char *string, *output, *command;
695 {
696 struct re_registers regs;
697 char *p;
698 char *p2;
699 static Boolean deleteRest = False;
700 static Boolean for_gdb_only = False;
701 int command_type = -1;
702 static unsigned int already_taken_care = 0;
703 Boolean previous_for_gdb_only;
704
705 if (output == NULL || strcmp(output, "") == 0)
706 return;
707
708 /* for GDB, the only things we want to filter are:
709
710 - the line displayed because of the -fullname option :
711 "\032\032/usr1/gnu_sun4/xdbx/pw.c:6:40:beg:0x22b0\n",
712
713 - the displayed info which goes into the display window,
714
715 - list and search outputs
716
717 */
718 if (!string)
719 string = "";
720
721 if (command)
722 command_type = match(command_pattern, command, C_ANY);
723
724 if ((command_type == C_EXEC)||(command_type == C_FINISH))
725 {
726 if ((re_match(output_pattern[O_EXEC_MESS_AFTER].buf,output,strlen(output),0,®s) > 0)
727 || (re_match(output_pattern[O_EXEC_MESS_BEFORE].buf,output,strlen(output),0,®s) > 0)
728 || (re_match(output_pattern[O_EXEC_GDB].buf,output,strlen(output),0,®s) > 0))
729 {
730 /* Remove display messages from output and print what is not a display */
731
732 if (Prompt) {
733 filter_display_info (output, already_taken_care);
734 for_gdb_only = False;
735 already_taken_care = 0;
736 deleteRest = False;
737 } else {
738 deleteRest = True;
739 }
740 return;
741 }
742 else /* does not match exec pattern yet */
743 {
744 if (deleteRest) /* if already matched before */
745 {
746 /* Remove display messages from output and print what is not a display */
747 if (Prompt)
748 {
749 filter_display_info (output, already_taken_care);
750 for_gdb_only = False;
751 already_taken_care = 0;
752 deleteRest = False;
753 }
754 return;
755 }
756 }
757 }
758
759
760 /* remember what was the output length was output was matched */
761 already_taken_care = strlen(output);
762
763 /* filter any line starting with \032\032 */
764
765 /* (PW)18NOV94: we have a problem with some system where the \032\032 comes in
766 several times. In that case we might end-up showing ^Z^Z in dialog window.
767 SO now do no test for end of line, and note that all following outputs are
768 for gdb, not for the user.
769 Here we assume that at least the double ^Z^Z is read in one piece.
770 */
771
772 previous_for_gdb_only = for_gdb_only;
773
774 p = strchr(string,'\032');
775 if (p && (*(p+1) == '\032') && (p == string || *(p-1) == '\n') /* && (p2 = strchr(p,'\n'))*/) {
776 if ((p2 = strchr(p,'\n'))) {
777 while ((*(p++) = *(++p2)));
778 } else {
779 *p = 0;
780 }
781 for_gdb_only = True;
782 }
783
784 if ((command_type == C_EXEC)||(command_type == C_FINISH)) {
785 if (!previous_for_gdb_only) {
786 AppendDialogText(string);
787 }
788 if (Prompt) {
789 for_gdb_only = False;
790 already_taken_care = 0;
791 deleteRest = False;
792 }
793 return;
794 }
795
796 if (Prompt)
797 {
798 char *s;
799
800 for_gdb_only = False;
801 already_taken_care = 0;
802 deleteRest = False;
803
804 s = XtNewString(output);
805 switch (command_type)
806 {
807 case C_DISPLAY:
808 if (match(output_pattern, s, O_DISPLAY) != -1)
809 strcpy(s, "");
810 break;
811
812 case C_DISPLAY_INFO:
813 /* (PW)7MAY91 : display error messages */
814 if (match(output_pattern, s, O_DISPLAY_INFO) != -1)
815 {
816 if (Token.mesg && strcmp(Token.mesg, ""))
817 {
818 AppendDialogText(Token.mesg);
819 bell(0);
820 }
821 strcpy(s, "");
822 }
823 break;
824
825 case C_SEARCH:
826 if (match(output_pattern, s, O_SEARCH) != -1)
827 strcpy(s, "");
828 break;
829 case C_LIST:
830 /* (PW)22MAY91 : display messages ") */
831 if (match(output_pattern, s, O_LIST) != -1)
832 {
833 if (Token.mesg && strcmp(Token.mesg, ""))
834 {
835 AppendDialogText(Token.mesg);
836 if (strstr(Token.mesg,"Source file is more recent than executable."))
837 bell(0); /* Warn user WYSIWYG not true */
838 }
839 strcpy(s, "");
840 }
841 break;
842 case C_PRINT:
843 if (PopupMode && /* if print goes in a window, don't display here */
844 (match(output_pattern, s, O_PRINT) != -1))
845 strcpy(s, "");
846 break;
847
848 default:
849 XtFree(s);
850 s = XtNewString(string); /* append 'string' only */
851 break;
852 }
853 AppendDialogText(s);
854 XtFree(s);
855 }
856 else /* no prompt yet */
857 {
858 switch (command_type)
859 {
860 case C_DISPLAY:
861 case C_DISPLAY_INFO:
862 case C_SEARCH:
863 case C_LIST:
864 case C_PRINT:
865 break;
866 default:
867 if (!previous_for_gdb_only) {
868 AppendDialogText(string);
869 }
870 break;
871 }
872 }
873
874 return;
875 }
876
877
878 /*--------------------------------------------------------------------------+
879 | |
880 | Function to filter 'source' command |
881 | |
882 | input : command (from .gdbinit or source command or keyboard), |
883 | echo is TRUE if source command must be echoed. |
884 | |
885 | output : TRUE if source command was recognized |
886 | |
887 | In case source command is recognized, it is executed here. |
888 | |
889 +--------------------------------------------------------------------------*/
890 int gdb_source_command(command,echo)
891 char *command;
892 int echo;
893 {
894 if (command && (match(command_pattern, command, C_SOURCE) != -1))
895 {
896 if (echo)
897 AppendDialogText(command);
898 source_handler();
899 return TRUE;
900 }
901
902 return FALSE;
903 }
904
905 /*--------------------------------------------------------------------------+
906 | |
907 | Function to filter 'define' & 'document' commands |
908 | |
909 | input : command (from .gdbinit or source command), |
910 | fp = file pointer. |
911 | |
912 | output : TRUE if define or document command was recognized |
913 | |
914 | In case the command is recognized, it is executed here. |
915 | |
916 +--------------------------------------------------------------------------*/
917 static int command_sent = 0; /* flag gdb is busy : send no more command to gdb. */
918
919 int gdb_define_command(command,fp)
920 char *command;
921 FILE *fp;
922 {
923 char s[LINESIZ];
924 int error_cmd;
925 int end_found;
926
927 if ((command && (match(command_pattern, command, C_DEFINE) != -1))
928 || (command && (match(command_pattern, command, C_DOCUMENT) != -1)))
929 {
930 AppendDialogText(command);
931
932 /* because silly gdb 4.0 displays nothing with def/doc command when
933 confirm is on (possibly a gdb bug) , I just reset confirm to on
934 just for this command !. */
935
936 if (new_gdb4())
937 query_gdb("set confirm on\n", PARSE_OFF | ECHO_OFF | FILTER_OFF);
938
939 write_dbx (command);
940
941 /*
942 gdb could ask :
943
944 "Redefine command \"%s\"? "
945 "Really redefine built-in command \"%s\"? "
946
947 gdb could display
948
949 "Type commands for definition of \"%s\".\n"
950 "End with a line saying just \"end\"
951
952 or
953 "Type documentation for \"%s\".\n"
954 "End with a line saying just \"end\".\n"
955
956 or
957 "Command \"%s\" is built-in."
958 */
959
960 error_cmd = FALSE;
961
962 /* read message from gdb */
963
964 while (1)
965 if (fgets(s, LINESIZ, dbxfp))
966 {
967 if (debug)
968 fprintf(stderr, "=>%s", s);
969
970 if (strstr(s," is built-in.")) /* error for document of built-in command */
971 {
972 AppendDialogText(s);
973 error_cmd = TRUE;
974 bell(0);
975 break;
976 }
977
978 if (strstr(s,"Redefine command ")
979 || strstr(s,"Really redefine built-in command "))
980 write_dbx ("y\n"); /* answer to question if any */
981 else
982 {
983 if (strcmp(s,"End with a line saying just \"end\".\n") == 0)
984 break;
985 }
986 }
987
988 /* write command definition */
989
990 end_found = FALSE;
991
992 while (fgets (s, LINESIZ, fp))
993 {
994 if (!error_cmd)
995 {
996 AppendDialogText(s);
997 write_dbx (s);
998 }
999
1000 if (match(command_pattern, s, C_END) != -1)
1001 {
1002 end_found = TRUE;
1003 break;
1004 }
1005 }
1006
1007 if ((!error_cmd) && (!end_found))
1008 {
1009 AppendDialogText("Error : missing \"end\" in file.\n");
1010 bell(0);
1011 write_dbx ("end\n");
1012 }
1013
1014 command_sent++; /* flag gdb is busy (because of read_gdb) */
1015 insert_command("end\n"); /* insert 'end' at head of queue */
1016 read_until_prompt (PARSE_OFF | ECHO_ON | FILTER_OFF); /* return when prompt */
1017
1018 if (new_gdb4()) /* reset confirm to off */
1019 query_gdb("set confirm off\n", PARSE_OFF | ECHO_OFF | FILTER_OFF);
1020
1021 return TRUE;
1022 }
1023
1024 return FALSE;
1025 }
1026
1027
1028 #ifndef NO_MY_FGETS
1029 /*
1030 * cope with non-blocking I/O correctly
1031 * ie: exit if child closes pty, but return if would block.
1032 *
1033 * This function seems to fail on some systems (??)
1034 *
1035 */
1036 static char *
1037 #ifdef __STDC__
1038 my_fgets(char *buf, int size, FILE *f)
1039 #else
1040 my_fgets(buf, size, f)
1041 char *buf;
1042 int size;
1043 FILE *f;
1044 #endif
1045 {
1046 char *orig_buf = buf;
1047
1048 while(size > 1) {
1049 int cc;
1050
1051 cc = read(fileno(f), buf, 1);
1052 if(cc == -1) {
1053 if(errno == EAGAIN || errno == EWOULDBLOCK) {
1054 break;
1055 }
1056 perror("read from gdb");
1057 exit(1);
1058 /*NOTREACHED*/
1059 }
1060 if(cc == 0) {
1061 #ifdef READ_ZERO_NOT_EOF /* for RS6000 */
1062 break;
1063 #else
1064 (void) fprintf(stderr, "EOF from gdb\n");
1065 exit(1);
1066 #endif
1067 /*NOTREACHED*/
1068 }
1069 buf++;
1070 size--;
1071 if(*(buf-1) == '\n')
1072 break;
1073 }
1074
1075 *buf = '\0';
1076 if (buf == orig_buf) {
1077 return NULL;
1078 } else {
1079 return(orig_buf);
1080 }
1081 }
1082 #endif /* NO_MY_FGETS */
1083
1084 /*--------------------------------------------------------------------------+
1085 | |
1086 | Read gdb output until fgets returns no string. |
1087 | |
1088 | The ouptut is process according to flags. |
1089 | |
1090 | In case the gdb prompt is found, the command on top of the |
1091 | command queue (ie, the one which is assumed to correspond |
1092 | to this output) is remove from the queue, and 'command_sent' |
1093 | is decremented to say that gdb is no longer busy. |
1094 | |
1095 +--------------------------------------------------------------------------*/
1096 static int parse_flags = PARSE_ON | ECHO_ON | FILTER_ON; /* last flags used in read_gdb */
1097
1098 void read_gdb (flags)
1099 int flags;
1100 {
1101 static char *output = NULL; /* buffer for gdb output */
1102 static char *next_string = NULL;
1103 static char *command;
1104 char *string = NULL;
1105 char *prompt_pointer;
1106 char s[LINESIZ];
1107 int before_prompt;
1108 Boolean more;
1109 Boolean local_prompt;
1110 parse_flags = flags; /* just remember flags for read_dbx() */
1111
1112 more = True;
1113 Prompt = False;
1114 local_prompt = False;
1115
1116 while (more) {
1117
1118 /* keep reading until no more or until prompt arrives */
1119 #ifdef NO_MY_FGETS
1120 while ((more = (fgets(s, LINESIZ, dbxfp) != NULL)))
1121 #else
1122 while ((more = (my_fgets(s, LINESIZ, dbxfp) != NULL)))
1123 #endif
1124 {
1125 if (debug)
1126 fprintf(stderr, "=>%s", s);
1127
1128 /* new gdb might add '>' characters in front of input for define commands,
1129 we have to test for them here !
1130 */
1131
1132 /* receive prompt? */
1133
1134 #if 1 /* (PW)16NOV94 : new gdb might add '>' characters in front of input
1135 when defining commands, we have to test for them here !
1136 so use strstr() to catch all prompts...
1137 */
1138 if ((prompt_pointer = strstr(s, dbxprompt)) != NULL)
1139 #else
1140 if (strncmp(s, dbxprompt, strlen(dbxprompt)) == 0)
1141 #endif
1142 {
1143 Prompt = True;
1144 local_prompt = True;
1145 before_prompt = prompt_pointer - s;
1146
1147 /* more stuff behind prompt? */
1148 if (s[before_prompt+ strlen(dbxprompt)]) {
1149 /* remember it */
1150 next_string = XtNewString(s+before_prompt+strlen(dbxprompt));
1151 }
1152 /* destroy contents */
1153 strcpy(s, "");
1154 if (debug)
1155 fprintf(stderr, " Prompt detected\n");
1156 }
1157
1158 string = concat(string, s);
1159 strcpy(s, "");
1160
1161 if (local_prompt) { /* do not read next line if prompt is found */
1162 break;
1163 }
1164 }
1165
1166 output = concat(output, string);
1167
1168 command = get_command(); /* read queue's top command */
1169
1170 if (flags & FILTER_ON) {
1171 filter (string, output, command);
1172 }
1173
1174 if ((flags & ECHO_ON) && local_prompt) {
1175 AppendDialogText(xdbxprompt);
1176 }
1177
1178 if (string) {
1179 XtFree(string);
1180 string = NULL;
1181 }
1182
1183 if (next_string) {
1184 string = concat(string, next_string);
1185 XtFree(next_string);
1186 next_string = NULL;
1187 }
1188
1189 if ((flags & PARSE_ON) && local_prompt) {
1190 parse (output, command, flags);
1191 }
1192
1193 /* note : it is important to decrement 'command_sent' AFTER
1194 parse() is executed, so that no other commands will mix-up
1195 the commands sent by the function handlers executed by parse().
1196 */
1197
1198 if (local_prompt) {
1199 delete_command(); /* remove top command from queue */
1200 if (command && command_sent)
1201 command_sent--;
1202 XtFree(output);
1203 output = NULL;
1204 local_prompt = False;
1205 }
1206 }
1207 }
1208
1209 /*--------------------------------------------------------------------------+
1210 | * |
1211 | * This is a callback procedure invoked everytime when input is pending |
1212 | * on the file descriptor to dbx. |
1213 | * o reads all the data available on the file descriptor line by line |
1214 | * into local variable 'string' and global variable 'output'. |
1215 | * 'output' records the entire dbx output whereas 'string' records |
1216 | * only the data read in this invocation of read_dbx(). |
1217 | * o in Echo mode, the contents in 'string' is edited by filter() |
1218 | * before it gets displayed on the dialog window. |
1219 | * o once the dbx prompt is read, calls parse() to analyse the dbx output |
1220 | * and take appropriate action. |
1221 | * |
1222 +--------------------------------------------------------------------------*/
1223 static volatile int in_read_dbx;
1224
1225 /* ARGSUSED */
1226 void read_dbx(master, source, id)
1227 XtPointer master;
1228 int *source;
1229 XtInputId *id;
1230 {
1231 if (in_read_dbx++) /* already running */
1232 return;
1233
1234 do {
1235 read_gdb (parse_flags);
1236
1237 /* do not write any more command, if prompt was not seen yet */
1238
1239 if (Prompt) {
1240 write_dbx_available ();
1241 }
1242
1243 } while (--in_read_dbx);
1244 }
1245
1246 /*--------------------------------------------------------------------------+
1247 | |
1248 | Read gdb output until prompt. |
1249 | The ouptut is process according to flags. |
1250 | |
1251 +--------------------------------------------------------------------------*/
1252 void read_until_prompt (flags)
1253 int flags;
1254 {
1255 Prompt = False;
1256 while (!Prompt)
1257 read_gdb (flags);
1258 }
1259
1260 /*--------------------------------------------------------------------------+
1261 | |
1262 | * Sends a command to gdb and read the corresponding output, directly |
1263 | * invoking the Xt input procedure, read_gdb(). |
1264 | * |
1265 | * Same as query_dbx() in dbx.c except that echo, filter and parse. |
1266 | * are passed in argument flags: |
1267 | * PARSE_ON | PARSE_OFF | ECHO_ON | ECHO_OFF | FILTER_ON | FILTER_OFF |
1268 | * |
1269 +--------------------------------------------------------------------------*/
1270 void query_gdb(command, flags)
1271 char *command;
1272 int flags;
1273 {
1274 command_sent++; /* flag gdb is busy */
1275
1276 write_dbx(command); /* send command to gdb */
1277
1278 insert_command(command); /* insert at head of queue */
1279
1280 read_until_prompt (flags); /* return when prompt */
1281
1282 /* test if we are at the top command, and if some commands are waiting */
1283
1284 write_dbx_available (); /* send next waiting command */
1285 }
1286
1287 /*--------------------------------------------------------------------------+
1288 | |
1289 | Function to send the first command of the command queue to gdb only in |
1290 | case gdb is waiting for a command. |
1291 | |
1292 | WARNING : we must test for 'source' command. |
1293 | |
1294 | The commands in the command queue are from the keyboard and from |
1295 | the buttons. |
1296 | |
1297 +--------------------------------------------------------------------------*/
1298 void write_dbx_available()
1299 {
1300 char *command;
1301
1302 if ((command = get_command ()))
1303 {
1304 if (command_sent++ == 0)
1305 {
1306 /* here, the source command is already displayed, say echo command = FALSE */
1307
1308 if (gdb_source_command (command, FALSE))
1309 {
1310 delete_command(); /* remove source command from top of queue */
1311 command_sent--;
1312 /* tell gdb to send its prompt */
1313 query_gdb(" \n", PARSE_OFF | ECHO_ON | FILTER_OFF);
1314 return;
1315 }
1316
1317 if (xxgdb_command (command, FALSE))
1318 {
1319 delete_command(); /* remove xxgdb command from top of queue */
1320 command_sent--;
1321 /* tell gdb to send its prompt */
1322 query_gdb(" \n", PARSE_OFF | ECHO_ON | FILTER_OFF);
1323 return;
1324 }
1325
1326 parse_flags = PARSE_ON | ECHO_ON | FILTER_ON; /* for read_gdb */
1327 write_dbx (command);
1328 Prompt = False;
1329 return; /* return with command_sent incremented */
1330 }
1331 else
1332 {
1333 if (command_sent) /* should never be zero ! (just to be safe) */
1334 command_sent--; /* command is not sent, restore previous value */
1335 return;
1336 }
1337 }
1338 }
1339
1340
1341 /*--------------------------------------------------------------------------+
1342 | |
1343 | Function to filter xxgdb only commands |
1344 | |
1345 | input : command (from .gdbinit or source command or keyboard), |
1346 | echo is TRUE if source command must be echoed. |
1347 | |
1348 | output : TRUE if source command was recognized |
1349 | |
1350 | In case source command is recognized, it is executed here. |
1351 | |
1352 +--------------------------------------------------------------------------*/
1353 int xxgdb_command (command, echo)
1354 char *command;
1355 int echo;
1356 {
1357 #ifdef CREATE_IO_WINDOW
1358 if (command && (!strcmp(command,"iowin\n"))) /* test for 'iowin' command */
1359 {
1360 if (echo)
1361 AppendDialogText(command);
1362 if (!iowinpid)
1363 {
1364 char ttycommand[50];
1365 create_io_window ();
1366 sprintf (ttycommand, "tty %s\n", iowintty);
1367 query_gdb (ttycommand, PARSE_OFF | ECHO_OFF | FILTER_OFF);
1368 }
1369 return TRUE;
1370 }
1371 #endif /* CREATE_IO_WINDOW */
1372
1373 return FALSE;
1374 }
1375