use _filtered routines for printing so symbolic addresses show up in the right place
[deliverable/binutils-gdb.git] / gdb / energize.c
CommitLineData
f823634c
SG
1/* Energize (formerly known as Cadillac) interface routines.
2 Copyright 1991, 1992 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "defs.h"
21#include "symtab.h"
22#include "inferior.h"
23#include "command.h"
24#include "bfd.h"
25#include "symfile.h"
26#include "objfiles.h"
27#include <sys/types.h>
28#include <sys/time.h>
29#include <sys/param.h>
509c1804
SG
30#include "energize/connection.h"
31#include "energize/genericreq.h"
32#include "energize/debuggerreq.h"
33#include "energize/debuggerconn.h"
34#include "energize/ttyconn.h"
f823634c
SG
35#include <varargs.h>
36#include <sys/stat.h>
37#ifdef USG
38#include <sys/file.h>
39#endif
40#include <fcntl.h>
41#include <sys/filio.h>
42#include <setjmp.h>
43#include <signal.h>
44#include <sys/errno.h>
45#include <termios.h>
46#include <string.h>
47
48/* Non-zero means that we're doing the energize interface. */
49int energize = 0;
50
00556177
SG
51/* Non-zero means we are reloading breakpoints, etc from the
52 Energize kernel, and we should suppress various messages */
53static int energize_reloading = 0;
54
f823634c
SG
55/* Connection block for debugger<=>kernel communications. */
56static Connection *conn = 0;
57
58/* fd for our socket to the kernel. */
59static int kerfd;
60
61/* The kernel's ID for this instance of the program. */
62static int program_id;
63
64static int instance_id;
65
66/* The fd for the pty associated with the inferior. */
67static int inferior_pty = -1;
68static int inferior_tty = -1;
69
70static int has_run = 0;
71
72extern int pgrp_inferior;
73
74extern char *source_path;
75
b5fee91e
SG
76/* The name of the executable file */
77static char *exec_file;
f823634c
SG
78
79/* Tell energize_command_line_input() where to get its text from */
80static int doing_breakcommands_message = 0;
81
82/* Stash command text here */
83static char *command_line_text = 0;
84static int command_line_length = 0;
85
86/* Flags returned by wait_for_events() */
87#define KERNEL_EVENT 1
88#define PTY_EVENT 2
89
90\f
91/* This routine redirects the output of fputs_filtered to the kernel so that
92 the user can see what's going on in his debugger window. */
93
94void
95energize_fputs(ptr)
96 const char *ptr;
97{
98 if (conn)
99 CVWriteTranscriptInfo (conn, instance_id, (char *)ptr);
100 else
101 fputs (ptr, stdout);
102}
103
104void
105energize_query(query, args)
106 char *query;
107 va_list args;
108{
109 char buf[100];
110
111 if (!energize)
112 return;
113
114 vsprintf(buf, query, args);
115
116 CVWriteQueryInfo(conn,
117 instance_id,
118 CQueryConfirm,
119 qno_unknown,
120 buf,
121 ""); /* transcript */
122}
123
124void
125energize_acknowledge_query(ack)
126 char *ack;
127{
128 CVWriteQueryInfo(conn,
129 instance_id,
130 CQueryAcknowleged,
131 0,
132 ack,
133 ""); /* transcript */
134}
135
136/* Copy all data from the pty to the kernel. */
137
138static void
139pty_to_kernel()
140{
141 CTtyRequest *req;
142 char buf[1024];
143 int cc;
144
145 while (1)
146 {
147 cc = read(inferior_pty, buf, sizeof(buf));
148
149 if (cc == 0
150 || (cc < 0
00556177
SG
151 && (errno == EWOULDBLOCK
152 || errno == EAGAIN)))
f823634c
SG
153 break;
154
155 if (cc < 0)
156 {
157 close(inferior_pty);
158 inferior_pty = -1;
00556177 159 perror("pty_to_kernel: pty read error");
f823634c
SG
160 break;
161 }
162
163 req = CWriteTtyRequest(conn, TextIORType);
164 CWriteVstringLen(conn, buf, cc);
165 CWriteLength(conn);
166 }
167 CWriteRequestBuffer(conn);
168}
169
170/* Copy data from the kernel to the pty. */
171
172static void
173kernel_to_pty(data, len)
174 char *data;
175 int len;
176{
177 int cc;
178
179 cc = write(inferior_pty, data, len);
180
181 if (cc != len)
182 {
183 if (cc < 0)
184 {
185 close(inferior_pty);
186 inferior_pty = -1;
00556177 187 perror("kernel_to_pty: pty write error");
f823634c
SG
188 return;
189 }
190 printf("Couldn't write all the data to the pty, wanted %d, got %d\n",
191 len, cc);
192 }
193}
194\f
195static char *
196full_filename(symtab)
197 struct symtab *symtab;
198{
199 int pathlen;
200 char *filename;
201
202 if (!symtab)
203 return NULL;
204
205 if (symtab->fullname)
206 return savestring(symtab->fullname, strlen(symtab->fullname));
207
00556177
SG
208 if (symtab->filename[0] == '/')
209 return savestring(symtab->filename, strlen(symtab->filename));
210
f823634c
SG
211 if (symtab->dirname)
212 pathlen = strlen(symtab->dirname);
213 else
214 pathlen = 0;
215 if (symtab->filename)
216 pathlen += strlen(symtab->filename);
217
218 filename = xmalloc(pathlen+1);
219
220 if (symtab->dirname)
221 strcpy(filename, symtab->dirname);
222 else
223 *filename = '\000';
224 if (symtab->filename)
225 strcat(filename, symtab->filename);
226
227 return filename;
228}
229
230/* Tell the energize kernel how high the stack is so that frame numbers (which
00556177 231 are relative to the current stack height make sense.
f823634c
SG
232
233 Calculate the number of frames on the stack, and the number of subroutine
234 invocations that haven't changed since the last call to this routine. The
235 second number is calculated by comparing the PCs of the current stack frames
236 to the PCs of the previous set of stack frames. The screw here is that a
237 subroutine may call several different procedures, which means that the PC
238 in its frame changes, even though you are still in the same subroutine. We
239 resolve this by converting the frames PC into the PC at the start of the
240 function (for efficiency, this is done only if the simple comparison test
241 fails). */
242
243struct pclist
244{
245 CORE_ADDR pc;
246 struct pclist *next;
247};
248
249/* Non-zero means that Energize kernel already knows how high the stack is. */
250static int stack_info_valid = 0;
251
252static void
253send_stack_info()
254{
255 struct pclist *pclist = 0, *pli, *opli;
256 static struct pclist *old_pclist;
257 FRAME frame;
258 int height, similar;
259
260 if (stack_info_valid)
261 return;
262
263 height = 0;
264 similar = 0;
265
266/* First, calculate the stack height, and build the new pclist */
267
268 for (frame = get_current_frame();
269 frame != 0;
270 frame = get_prev_frame(frame))
271 {
272 (height)++;
273 pli = (struct pclist *)xmalloc(sizeof(struct pclist));
274
275 pli->pc = frame->pc;
276 pli->next = pclist;
277 pclist = pli;
278 }
279
280/* Now, figure out how much of the stack hasn't changed */
281
282 for (pli = pclist, opli = old_pclist;
283 pli != 0 && opli != 0;
284 pli = pli->next, opli = opli->next, (similar)++)
285 {
286 if ((pli->pc != opli->pc)
287 && (get_pc_function_start(pli->pc)
288 != get_pc_function_start(opli->pc)))
289 break;
290 }
291
292/* Free up all elements of the old pclist */
293
294 opli = old_pclist;
295
296 while (opli)
297 {
298 pli = opli->next;
299 free (opli);
300 opli = pli;
301 }
302
303 old_pclist = pclist; /* Install the new pclist */
304
305 CVWriteStackSizeInfo(conn,
306 instance_id,
307 height, /* Frame depth */
308 CInnerFrameIs0,
309 similar, /* Frame diff */
310 "" /* Transcript */
311 );
312
313 stack_info_valid = 1;
314}
315
5ca812d4
SG
316/* Tell the Energize server about the file and line # that corresponds to pc,
317 and which stack frame level that pc corresponds to. */
318
319static void
320send_location(pc, frame_level)
321 CORE_ADDR pc;
322 int frame_level;
323{
324 char *funcname, *filename;
325 struct symtab_and_line sal;
326 struct symbol *symbol;
327
328 sal = find_pc_line(pc, 0);
329 symbol = find_pc_function(pc);
330
331 funcname = symbol ? symbol->name : "";
332 filename = full_filename(sal.symtab);
333
334 send_stack_info();
335
336 CVWriteStackFrameInfo(conn,
337 instance_id,
338 sal.line,
339 CFileLinePos,
340 frame_level,
341 funcname,
342 filename,
343 "" /* XXX ? transcript */
344 );
345 if (filename)
346 free(filename);
347}
348
f823634c
SG
349/* Tell the kernel where we are in the program, and what the stack looks like.
350 */
351
352static void
353send_status()
5ca812d4
SG
354{
355 char *funcname;
f823634c 356 struct symbol *symbol;
f823634c
SG
357 static int sent_prog_inst = 0;
358
5ca812d4
SG
359 symbol = find_pc_function(stop_pc);
360 funcname = symbol ? symbol->name : "";
361
f823634c
SG
362 if (!has_run)
363 return;
364
365 if (inferior_pid == 0) /* target has died */
366 {
367 CVWriteProgramTerminatedInfo(conn,
368 instance_id,
369 ""
370 );
371 return;
372 }
373
f823634c
SG
374 if (!sent_prog_inst)
375 {
376 sent_prog_inst = 1;
377 CVWriteProgramInstanceInfo(conn,
378 program_id,
379 instance_id,
380 "", /* hostname */
381 "", /* arglist */
382 ""
383 );
384 }
385
5ca812d4
SG
386 send_location(stop_pc,
387 selected_frame_level); /* Had better be 0! */
f823634c
SG
388
389 CVWriteProgramStoppedInfo(conn,
390 instance_id,
391 0, /* XXX - breakpoint # or signal # */
392 CDebuggerCommand,
393 funcname,
394 "" /* XXX ? transcript */
395 );
396
f823634c
SG
397}
398
399/* Call this to output annotated function names. Names will be demangled if
400 necessary. arg_mode contains flags that are passed on to cplus_demangle. */
401
402void
403energize_annotate_function(funcname, arg_mode, level)
404 char *funcname;
405 int arg_mode;
406 int level;
407{
408 extern int demangle;
409 char *demangled_name = NULL;
410
411 if (funcname == NULL)
412 return;
413
414 if (demangle)
415 {
416 demangled_name = cplus_demangle(funcname, arg_mode);
417
418 if (demangled_name)
5ca812d4
SG
419 {
420 funcname = demangled_name;
421 printf_filtered("'");
422 }
f823634c
SG
423 }
424
425 send_stack_info();
426
427 if (level < 0) level = 0;
428
429 CVWriteBackTraceEntryInfo(conn,
430 instance_id,
431 level, /* frameNo */
432 funcname);
433
434 if (demangled_name)
5ca812d4
SG
435 {
436 free(demangled_name);
437 printf_filtered("'");
438 }
f823634c
SG
439}
440
441/* Call this just prior to printing out the name & value of a variable. This
442 tells the kernel where to annotate the output. */
443
444/* The args are:
445 expression - A text handle on what GDB can use to reference this value.
446 This can be a symbol name, or a convenience var, etc...
447 symbol - Used to determine the scope of the data. May be NULL.
448 type - Determines if we have a pointer ref, and the print name of the type.
449 Used in ShowValue message.
450 valaddr - The address in target memory of the data.
451 field - The field name of the struct or union element being referenced.
452*/
453
454static char cum_expr[200]; /* Cumulative expression */
455static char *expr_stack[100] = {cum_expr}; /* Pointers to end of expressions */
456static char **last_expr = expr_stack; /* Current expr stack pointer */
457
458void
459energize_start_variable_annotation(expression, symbol, type, valaddr, field)
460 char *expression;
461 struct symbol *symbol;
462 struct type *type;
463 CORE_ADDR valaddr;
464 char *field;
465{
466 int ref_type;
467 int stor_cl;
468 enum type_code type_code;
469 enum address_class sym_class;
470 char *type_cast;
471
472 if (!energize)
473 return;
474
475 send_stack_info();
476
477 strcpy(*last_expr++, expression);
478 *last_expr = *(last_expr-1) + strlen(expression);
479
480 switch (TYPE_CODE(type))
481 {
482 case TYPE_CODE_ARRAY:
483 case TYPE_CODE_STRUCT:
484 case TYPE_CODE_UNION:
485 case TYPE_CODE_ENUM:
486 case TYPE_CODE_INT:
487 case TYPE_CODE_FLT:
488 ref_type = CValueValueRef;
489 break;
490 case TYPE_CODE_PTR:
491 ref_type = CValuePointerRef;
492 break;
493 default:
494 ref_type = CValueUndefRef;
495 break;
496 }
497
498/* Make sure that pointer points at something we understand */
499
500 if (ref_type == CValuePointerRef)
501 switch (TYPE_CODE(TYPE_TARGET_TYPE(type)))
502 {
503 case TYPE_CODE_PTR:
504 case TYPE_CODE_ARRAY:
505 case TYPE_CODE_STRUCT:
506 case TYPE_CODE_UNION:
507 case TYPE_CODE_ENUM:
508 case TYPE_CODE_INT:
509 case TYPE_CODE_FLT:
510 break;
511 default:
512 ref_type = CValueUndefRef;
513 break;
514 }
515
516 if (symbol)
517 {
518 sym_class = SYMBOL_CLASS(symbol);
519
520 switch (sym_class)
521 {
522 case LOC_CONST:
523 case LOC_CONST_BYTES:
524 stor_cl = CValueStorStaticConst;
525 break;
526 case LOC_STATIC:
527 stor_cl = CValueStorStaticVar;
528 break;
529 case LOC_REGISTER:
530 case LOC_REGPARM:
531 stor_cl = CValueStorRegister;
532 break;
533 case LOC_ARG:
534 case LOC_REF_ARG:
535 case LOC_LOCAL:
536 case LOC_LOCAL_ARG:
537 stor_cl = CValueStorLocalVar;
538 break;
539 default:
540 stor_cl = CValueStorUndef;
541 break;
542 }
543 }
544 else
545 stor_cl = CValueStorUndef;
546
547 type_cast = TYPE_NAME(type);
548
549 CVWriteValueBeginInfo(conn,
550 instance_id,
551 valaddr,
552 ref_type,
553 stor_cl,
554 0, /* XXX - frameno */
555 cum_expr,
556 field,
557 type_cast,
558 ""); /* transcript */
559}
560
561void
562energize_end_variable_annotation()
563{
564 if (!energize)
565 return;
566
567 last_expr--; /* Pop the expr stack */
568 **last_expr = '\000'; /* Cut off the last part of the expr */
569
570 CVWriteValueEndInfo(conn,
571 instance_id,
572 ""); /* transcript */
573}
574\f
575/* Tell the kernel that the target is now running. */
576
577static void
578go_busy()
579{
580 CVWriteProgramBusyInfo(conn,
581 instance_id,
582 ""); /* XXX ? transcript */
583 CWriteRequestBuffer(conn); /* Must take place synchronusly! */
584 stack_info_valid = 0;
585}
586
587\f
588void
589energize_symbol_file(objfile)
590 struct objfile *objfile;
591{
592 if (!energize)
593 return;
594
595 CVWriteSymbolTableInfo(conn,
596 objfile->name,
597 ""); /* Transcript */
598}
599
600/* execute_command_1(echo, queue, cmd, args) - echo - non-zero means echo the
601 command. queue - non-zero means don't execute it now, just save it away for
602 later. cmd - string containing printf control sequences. args - list of
603 arguments needed by those control sequences.
604 */
605
606/* Linked list of queued up commands */
607static struct command_line *queued_commands = 0;
608static struct command_line *last_queued_command = 0;
609
610/* Call this routine to save a command for later. The command string is
611 copied into freshly malloc'ed memory. */
612
613static void
614queue_command(cmd)
615 char *cmd;
616{
617 char *buf;
618 struct command_line *cl;
619 unsigned long s;
620
621 s = (strlen(cmd) + 1) + 7 & ~(unsigned long)7;
622
623 buf = (char *)xmalloc(s + sizeof(struct command_line));
624 cl = (struct command_line *)(buf + s);
625 cl->next = 0;
626 cl->line = buf;
627
628 strncpy(cl->line, cmd, s);
629
630 if (queued_commands)
631 last_queued_command->next = cl;
632 else
633 queued_commands = cl;
634
635 last_queued_command = cl;
636}
637
638/* Call this procedure to take a command off of the command queue. It returns
639 a pointer to a buf which the caller is responsible for freeing. NULL is
640 returned if there are no commands queued. */
641
642static char *
643dequeue_command()
644{
645 struct command_line *cl;
646 char *cmd;
647
648 cl = queued_commands;
649
650 if (!cl)
651 return NULL;
652
653 queued_commands = cl->next;
654
655 return cl->line;
656}
657
658static void
659execute_command_1(va_alist)
660 va_dcl
661{
662 char buf[100]; /* XXX - make buf dynamic! */
663
664 int echo;
665 int queue;
666 char *cmd;
667 va_list args;
668
669 va_start(args);
f823634c 670 echo = va_arg(args, int);
00556177 671
f823634c
SG
672 queue = va_arg(args, int);
673 cmd = va_arg(args, char *);
674
675 vsprintf(buf, cmd, args);
676
677 if (queue)
678 queue_command(buf);
679 else
680 {
681 if (echo)
682 printf_filtered("%s\n", buf);
683 execute_command(buf, 1);
684 }
685
686 va_end(args);
687}
688
689#ifdef KERNEL_RECORD
690FILE *kerout;
691
692static int
693kernel_record(fd, ptr, num)
694 int fd, num;
695 char *ptr;
696
697{
698 fwrite(ptr, num, 1, kerout);
699 fflush(kerout);
700 return write(fd, ptr, num);
701}
702#endif
703
704void
705energize_condition_breakpoint(b)
706 struct breakpoint *b;
707{
708 if (energize)
709 CVWriteBreakConditionInfo(conn,
710 instance_id,
711 b->number,
712 b->cond_string ? b->cond_string : "",
713 "" /* transcript */
714 );
715}
716
717void
718energize_commands_breakpoint(b)
719 struct breakpoint *b;
720{
721 struct command_line *l;
722
723 if (!energize)
724 return;
725
726 CVWriteBreakCommandBegInfo(conn,
727 instance_id,
728 b->number,
729 ""); /* transcript */
730
731 for (l = b->commands; l; l = l->next)
732 CVWriteBreakCommandEntryInfo(conn,
733 instance_id,
734 l->line,
735 ""); /* transcript */
736
737 CVWriteBreakCommandEndInfo(conn,
738 instance_id,
739 ""); /* transcript */
740}
741
742static void
743breakpoint_notify(b, action)
744 struct breakpoint *b;
745 int action;
746{
747 struct symbol *sym;
748 char *funcname = "";
749 char *filename;
750 char *included_in_filename = "";
751
00556177
SG
752 if (!energize
753 || energize_reloading) /* Don't notify energize about breakpoint changes, as it's about to send us
754 a new bunch. */
f823634c
SG
755 return;
756
757 if (b->type != bp_breakpoint)
758 return;
759
760 filename = full_filename(b->symtab);
761
762 sym = find_pc_function(b->address);
763 if (sym)
764 funcname = SYMBOL_NAME(sym);
765
766 CVWriteBreakpointInfo (conn,
767 instance_id,
768 b->number,
769 b->line_number,
770 CFileLinePos,
771 CBreakOnInstrAccess,
772 action,
773 b->ignore_count,
774 funcname,
775 filename ? filename : "",
776 "", /* included_in_filename */
777 "" /* transcript */
778 );
779
780 if (b->commands)
781 energize_commands_breakpoint(b);
782
783 energize_condition_breakpoint(b);
784
785 if (filename)
786 free(filename);
787}
788
789void
790energize_create_breakpoint(b)
791 struct breakpoint *b;
792{
793 breakpoint_notify(b, CEnableBreakpoint);
794}
795
796void
797energize_delete_breakpoint(b)
798 struct breakpoint *b;
799{
800 breakpoint_notify(b, CDeleteBreakpoint);
801}
802
803void
804energize_enable_breakpoint(b)
805 struct breakpoint *b;
806{
807 breakpoint_notify(b, CEnableBreakpoint);
808}
809
810void
811energize_disable_breakpoint(b)
812 struct breakpoint *b;
813{
814 breakpoint_notify(b, CDisableBreakpoint);
815}
816
817void
818energize_ignore_breakpoint(b)
819 struct breakpoint *b;
820{
821 breakpoint_notify(b, CBreakAttrUnchanged);
822}
823\f
824/* Open up a pty and its associated tty. Return the fd of the tty. */
825
5ca812d4 826#ifndef NCR486
f823634c
SG
827static void
828getpty()
829{
830 int n, ptyfd, ttyfd;
831 static char dev[30];
832 struct stat statbuf;
833 struct termios termios;
834
835#define HIGHPTY (('z' - 'p') * 16 - 1)
836
837 for (n = 0; n <= HIGHPTY; n++)
838 {
839 sprintf(dev, "/dev/pty%c%x", n/16 + 'p', n%16);
840 if (stat(dev, &statbuf))
841 break;
842 ptyfd = open(dev, O_RDWR);
843 if (ptyfd < 0)
844 continue;
845 sprintf(dev, "/dev/tty%c%x", n/16 + 'p', n%16);
846 ttyfd = open(dev, O_RDWR);
5ca812d4
SG
847 if (ttyfd < 0)
848 {
849 close(ptyfd);
850 continue;
851 }
f823634c
SG
852
853 /* Setup pty for non-blocking I/O. Also make it give us a SIGIO when
854 there's data available. */
855
856 n = fcntl(ptyfd, F_GETFL, 0);
857 fcntl(ptyfd, F_SETFL, n|FNDELAY|FASYNC);
858 fcntl(ptyfd, F_SETOWN, getpid());
859
860 tcgetattr(ttyfd, &termios);
861 termios.c_oflag &= ~OPOST; /* No post-processing */
862 tcsetattr(ttyfd, TCSANOW, &termios);
863
864 inferior_pty = ptyfd;
865 inferior_tty = ttyfd;
866 return;
867 }
868
869 error ("getpty: can't get a pty\n");
870}
5ca812d4
SG
871#endif
872/* Alternate getpty for NCRs */
873
874#ifdef NCR486 /* LTL */
875#define MAX_PTM_TRY 16
876#define MAX_GRANTPT_TRY 4
877static void
878getpty()
879{
880 char *slavename;
881 extern char *ptsname();
882 int j, i;
883 int n, mfd, sfd;
00556177 884 struct stat statbuf;
5ca812d4
SG
885 struct termios termios;
886
00556177
SG
887 if (stat("/dev/ptmx",&statbuf)) error ("getpty: can't locate master\n");
888
5ca812d4
SG
889 /* Number of pseudo-terms is tuneable(16 - 255). System default is 16. */
890 for (i = 0; i < MAX_PTM_TRY; i++)
891 {
892 mfd = open("/dev/ptmx", O_RDWR); /* get the master */
893
894 if (mfd < 0)
895 continue;
896
897 if (grantpt(mfd) < 0) /* get a slave */
898 for (j = 0; j < MAX_GRANTPT_TRY; j++)
899 if (grantpt(mfd) == 0 )
900 {
901 close(mfd);
902 continue;
903 }
904
905 if (unlockpt(mfd) < 0)
906 { /* unlock the slave so he can be opened */
907 close(mfd);
908 continue;
909 }
910
911 slavename = ptsname(mfd); /* get the slave device name */
00556177
SG
912 if (slavename)
913 break; /* Success! */
5ca812d4 914
00556177
SG
915 close(mfd);
916 continue;
917 }
5ca812d4 918
00556177 919 sfd = open(slavename, O_RDWR);
5ca812d4 920
00556177
SG
921 if (sfd < 0)
922 {
923 close(mfd);
924 error ("getpty: can't open slave\n");
5ca812d4 925 }
00556177
SG
926
927 if (slavename==NULL && i >= MAX_PTM_TRY)
928 error ("getpty: can't get a pts\n");
929
930 /* setup mty for non-blocking I/O. */
931
932 if ((n = fcntl(mfd, F_GETFL)) < 0)
933 perror ("getpty: fcntl F_GETFL failed");
934 else if (fcntl(mfd, F_SETFL, n|O_NDELAY) <0)
935 perror("getpty:fcntl F_SETFL fails");
936
937 /* set up for async i/o - V.4 will send SIGPOLL when data available */
938
939 if (ioctl (mfd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
940 perror ("getpty: ioctl I_SETSIG failed");
941
942 /* fcntl(mfd, F_SETOWN,getpid()); SVR4 does not support this */
943
944 if (ioctl(sfd, I_PUSH, "ptem")) perror ("getpty: ioctl I_PUSH fails");
945 if (ioctl(sfd, I_PUSH, "ldterm")) perror ("getpty: ioctl I_PUSH fails");
946
947 if (tcgetattr(sfd, &termios)) perror("getpty: tcgetattr fails");
948 termios.c_oflag &= ~OPOST; /* no post-processing */
949 if (tcsetattr(sfd, TCSANOW, &termios)) perror("getpty: tcsetattr fails");
950
951 inferior_pty=mfd;
952 inferior_tty=sfd;
953
954 return;
5ca812d4 955}
00556177
SG
956
957#endif /* NCR486 */
f823634c
SG
958\f
959/* Examine a protocol packet from the driver. */
960
961static void
962kernel_dispatch(queue)
963 int queue; /* Non-zero means we should just queue up
964 commands. */
965{
966 register CHeader *head;
967
968 head = (CHeader *)CPeekNextRequest (conn);
969 if (head == NULL)
970 {
971 fprintf (stderr, "EOF on kernel read!\n");
972 exit (1);
973 }
974
975 if (head->reqType < LastTtyRequestRType)
976 {
977 CTtyRequest* req = CReadTtyRequest (conn);
978 switch (req->head.reqType)
979 {
980 case AcceptConnectionRType:
981 /* Tell the rest of the world that energize is now set up */
982 CSkipRequest (conn);
983 break;
984
985 case RefuseConnectionRType:
986 fprintf (stderr, "Debugger connection refused\n");
987 exit (1);
988
989 case KillProgramRType:
990 exit (0);
991
992 case TextIORType:
993 {
994 char *p;
995 ReqLen len;
996
997 p = CGetVstring(conn, &len);
998 kernel_to_pty(p, len);
999 }
1000 break;
1001 default:
509c1804 1002 fprintf(stderr, "Unknown Tty request type = %d\n",
f823634c
SG
1003 req->head.reqType);
1004 break;
1005 }
1006 }
1007 else
1008 {
1009 CVDebuggerRequest *req = CVReadDebuggerRequest (conn);
1010 if (!req)
1011 {
1012 fprintf (stderr, "CVReadDebuggerRequest returned NULL, type = %d\n",
1013 head->reqType);
1014 exit(1);
1015 }
1016
1017 switch (req->head.request->reqType)
1018 {
1019 case OpenProgramInstanceRType:
1020 {
1021 char *arglist, buf[100]; /* XXX - Make buf dynamic! */
1022 int arglen;
1023 /* XXX - should notice when program_id changes */
1024 arglist = req->openProgramInstance.progArglist.text;
1025 arglen = req->openProgramInstance.progArglist.byteLen;
1026
1027 execute_command_1(1, queue, "break main");
1028 execute_command_1(1, queue, "enable delete $bpnum");
1029 if (arglist)
1030 {
1031 execute_command_1(1, queue, "set args %.*s", arglen, arglist);
1032 }
1033 execute_command_1(1, queue, "run");
1034 }
1035 break;
1036 case SearchPathRType:
1037 directory_command(req->searchPath.searchPath.text, 0);
1038 break;
1039 case QuitDebuggerRType:
1040 execute_command_1(1, queue, "quit");
1041 break;
1042 case RunRType:
1043 if (req->run.request->useArglist == CNewArglist)
1044 {
1045 execute_command_1(1, queue, "set args %.*s",
1046 req->run.progArglist.byteLen,
1047 req->run.progArglist.text);
1048 }
1049 execute_command_1(1, queue, "run");
1050 break;
1051 case ContinueRType:
1052 execute_command_1(1, queue, "continue");
1053 break;
1054 case StepRType:
1055 execute_command_1(1, queue, "step %d", req->step.request->stepCount);
1056 break;
1057 case NextRType:
1058 execute_command_1(1, queue, "next %d", req->next.request->nextCount);
1059 break;
1060 case ChangeStackFrameRType:
1061 switch (req->changeStackFrame.request->frameMovement)
1062 {
1063 case CToCurrentStackFrame:
1064 execute_command_1(1, queue, "frame %d",
1065 req->changeStackFrame.request->frameNo);
1066 break;
1067 case CToInnerStackFrame:
1068 execute_command_1(1, queue, "down %d",
1069 req->changeStackFrame.request->frameNo);
1070 break;
1071 case CToOuterStackFrame:
1072 execute_command_1(1, queue, "up %d",
1073 req->changeStackFrame.request->frameNo);
1074 break;
1075 case CToAbsoluteStackFrame:
1076 execute_command_1(1, queue, "frame %d",
1077 req->changeStackFrame.request->frameNo);
1078 break;
1079 }
1080 break;
1081 case BackTraceRType:
1082 /* XXX - deal with limit??? */
1083 execute_command_1(1, queue, "backtrace");
1084 break;
1085 case FinishRType:
1086 execute_command_1(1, queue, "finish");
1087 break;
1088 case TerminateProgramRType:
1089 execute_command_1(1, queue, "kill");
1090 break;
1091 case NewBreakpointRType:
1092 {
1093 char *tail;
1094 int skipped;
1095
1096 tail = strrchr(req->newBreakpoint.fileName.text, '/');
1097 if (!tail)
1098 tail = req->newBreakpoint.fileName.text;
1099 else
1100 tail++;
1101 skipped = tail - req->newBreakpoint.fileName.text;
1102 execute_command_1(1, queue, "break %.*s:%d",
1103 req->newBreakpoint.fileName.byteLen - skipped,
1104 tail,
1105 req->newBreakpoint.request->fileLinePos);
1106 }
1107 break;
1108 case StopRType:
00556177 1109 kill(-pgrp_inferior, SIGINT);
f823634c
SG
1110 break;
1111 case UserInputRType:
1112 {
1113 char *text;
1114 long len;
1115
1116 /* XXX - should really break command up into seperate lines
1117 and spoon-feed it to execute_command */
1118
1119 text = req->userInput.userInput.text;
1120 len = req->userInput.userInput.byteLen;
1121
1122 if (text[len-1] == '\n') text[len-1] = '\000';
1123
1124 while (*text == ' ' || *text == '\t') text++;
1125
1126 if (strcmp(text, "]*[") == 0) /* XXX - What does this mean??? */
1127 break;
1128
1129 if (*text != '\000')
1130 execute_command_1(0, queue, "%s", text);
1131 else
1132 print_prompt(); /* User just typed a blank line */
1133 }
1134 break;
1135 case QueryResponseRType:
1136 {
1137 char *resp;
1138
1139 if (req->queryResponse.request->response)
1140 resp = "y";
1141 else
1142 resp = "n";
1143 execute_command_1(1, 1, resp);
1144 printf_filtered("%s\n", resp);
1145 }
1146 break;
1147 case ChangeBreakpointRType:
1148 switch (req->changeBreakpoint.request->breakpointAttr)
1149 {
1150 case CBreakAttrUnchanged:
1151 execute_command_1(1, queue, "ignore %d %d",
1152 req->changeBreakpoint.request->breakpointId,
1153 req->changeBreakpoint.request->ignoreCount);
1154 break;
1155 case CEnableBreakpoint:
1156 execute_command_1(1, queue, "enable %d",
1157 req->changeBreakpoint.request->breakpointId);
1158 break;
1159 case CDisableBreakpoint:
1160 execute_command_1(1, queue, "disable %d",
1161 req->changeBreakpoint.request->breakpointId);
1162 break;
1163 case CDeleteBreakpoint:
1164 execute_command_1(1, queue, "delete %d",
1165 req->changeBreakpoint.request->breakpointId);
1166 break;
1167 case CEnableDisableBreakpoint:
1168 execute_command_1(1, queue, "enable once %d",
1169 req->changeBreakpoint.request->breakpointId);
1170 break;
1171 case CEnableDeleteBreakpoint:
1172 execute_command_1(1, queue, "enable delete %d",
1173 req->changeBreakpoint.request->breakpointId);
1174 break;
1175 default:
1176 printf_filtered("ChangeBreakpointRType: unknown breakpointAttr\n");
1177 printf_filtered(" breakpointAttr = %d\n",
1178 req->changeBreakpoint.request->breakpointAttr);
1179 printf_filtered(" breakpointId = %d\n",
1180 req->changeBreakpoint.request->breakpointId);
1181 printf_filtered(" breakpointType = %d\n",
1182 req->changeBreakpoint.request->breakpointType);
1183 printf_filtered(" ignoreCount = %d\n",
1184 req->changeBreakpoint.request->ignoreCount);
1185 break;
1186 }
1187 break;
1188 case BreakConditionRType:
1189 execute_command_1(1, queue, "condition %d %.*s",
1190 req->breakCondition.request->breakpointId,
1191 req->breakCondition.condition.byteLen,
1192 req->breakCondition.condition.text);
1193 break;
1194 case BreakCommandsRType:
1195 /* Put pointers to where energize_command_line_input() can find
1196 them. */
1197 doing_breakcommands_message = 1;
1198 command_line_length = req->breakCommands.commands.byteLen;
1199 command_line_text = req->breakCommands.commands.text;
1200 execute_command_1(1, queue, "commands %d",
1201 req->breakCommands.request->breakpointId);
1202 command_line_text = (char *)NULL;
1203 command_line_length = 0;
1204 doing_breakcommands_message = 0;
1205 break;
1206 case ShowValueRType:
1207 {
1208 char expr[100], *p = expr;
1209
1210 expr[0] = 0;
1211
1212 if (req->showValue.request->ref_type == CValuePointerRef)
1213 strcat(expr, "* ");
1214
1215 if (req->showValue.type_cast.byteLen)
1216 {
1217 strcat(expr, "(");
1218 strncat(expr, req->showValue.type_cast.text,
1219 req->showValue.type_cast.byteLen);
1220 strcat(expr, ") ");
1221 }
1222
1223 if (req->showValue.field.byteLen)
1224 strcat(expr, "(");
1225
1226 strncat(expr, req->showValue.expression.text,
1227 req->showValue.expression.byteLen);
1228
1229 if (req->showValue.field.byteLen)
1230 {
1231 strcat(expr, ")");
1232
1233 strncat(expr, req->showValue.field.text,
1234 req->showValue.field.byteLen);
1235 }
1236
1237 execute_command_1(1, queue, "print %s", expr);
1238 }
1239 break;
1240 case SetValueRType:
1241 {
1242 char expr[100], *p = expr;
1243
1244 expr[0] = 0;
1245
1246 if (req->setValue.request->ref_type == CValuePointerRef)
1247 strcat(expr, "* ");
1248
1249#if 0
1250 if (req->setValue.type_cast.byteLen)
1251 {
1252 strcat(expr, "(");
1253 strncat(expr, req->setValue.type_cast.text,
1254 req->setValue.type_cast.byteLen);
1255 strcat(expr, ") ");
1256 }
1257#endif
1258 if (req->setValue.field.byteLen)
1259 strcat(expr, "(");
1260
1261 strncat(expr, req->setValue.expression.text,
1262 req->setValue.expression.byteLen);
1263
1264 if (req->setValue.field.byteLen)
1265 {
1266 strcat(expr, ")");
1267
1268 strncat(expr, req->setValue.field.text,
1269 req->setValue.field.byteLen);
1270 }
1271
1272 execute_command_1(1, queue, "print %s = (%s) %s", expr,
1273 req->setValue.type_cast.text,
1274 req->setValue.value.text);
1275 }
1276 break;
509c1804 1277 case DynamicLoadRType:
b5fee91e
SG
1278 {
1279 char *filename;
1280
1281 filename = req->dynamicLoad.filenames.byteLen ?
1282 req->dynamicLoad.filenames.text : exec_file;
1283
1284 switch (req->dynamicLoad.request->action)
1285 {
1286 case CDynamicLoadUpdateSymtab:
00556177
SG
1287 energize_reloading = 1;
1288 execute_command_1(1, queue, "set confirm no");
1289 execute_command_1(1, queue, "delete");
1290/* execute_command_1(1, queue, "set $bpnum=1");*/ /* Use this to reset breakpoint #s */
b5fee91e
SG
1291 execute_command_1(1, queue, "exec-file %s", filename);
1292 execute_command_1(1, queue, "symbol-file %s", filename);
00556177
SG
1293 execute_command_1(1, queue, "set confirm yes");
1294 energize_reloading = 0;
1295 break;
1296 case CDynamicLoadRestoreStart:
1297 break;
1298 case CDynamicLoadRestoreEnd: /* Not used anymore??? */
1299 printf_filtered("\n[Target has changed, automatic restoration of state has been done.]\n");
1300 print_prompt();
b5fee91e
SG
1301 break;
1302 default:
1303 printf_filtered("DynamicLoadRType: unknown action=%d, filename=%s\n",
1304 req->dynamicLoad.request->action,
1305 req->dynamicLoad.filenames.text);
1306 break;
1307 }
1308 }
509c1804 1309 break;
f823634c 1310 default:
509c1804 1311 fprintf(stderr, "Unknown Debugger request type = %d\n",
f823634c
SG
1312 req->head.request->reqType);
1313 break;
1314 }
1315 free (req); /* Should probably call CVFreeDebuggerRequest() here, but
1316 can't do so if interrupt level has mucked with req->
1317 request. CVFreeDebuggerRequest() only ends up calling
1318 free() anyway! */
1319 }
1320}
1321\f
1322/* Return a bitmask indicating if the kernel or the pty did something
1323 interesting. Set poll to non-zero if you don't want to wait. */
1324
1325static int
1326wait_for_events(poll)
1327 int poll;
1328{
1329 fd_set readfds;
1330 int numfds;
1331 int eventmask = 0;
1332 static struct timeval tv = {0};
1333
1334 /* Output all pending requests. */
1335 CWriteRequestBuffer(conn);
1336
1337 FD_ZERO(&readfds);
1338
1339 /* Wait till there's some activity from the kernel or the pty. */
1340 do
1341 {
1342 FD_SET(kerfd, &readfds);
00556177
SG
1343
1344 FD_SET(inferior_pty, &readfds);
1345
f823634c
SG
1346 if (poll)
1347 numfds = select(sizeof(readfds)*8, &readfds, 0, 0, &tv);
1348 else
1349 numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
1350 }
1351 while (numfds <= 0 && !poll);
1352
00556177
SG
1353 if (numfds == 0)
1354 return 0;
1355
f823634c
SG
1356 if (FD_ISSET(inferior_pty, &readfds))
1357 eventmask |= PTY_EVENT;
1358
1359 if (FD_ISSET(kerfd, &readfds))
1360 eventmask |= KERNEL_EVENT;
1361
1362 return eventmask;
1363}
1364\f
1365/* This is called from read_command_lines() to provide the text for breakpoint
1366 commands, which is supplied in a BreakCommands message. Each call to this
1367 routine supplies a single line of text, with the newline removed. */
1368
1369/* This routine may be invoked in two different contexts. In the first, it
1370 is being called as a result of the BreakCommands message. In this case,
1371 all of the command text is immediately available. In the second case, it is
1372 called as a result of the user typing the 'command' command. The command
1373 text then needs to be glommed out of UserInput messages (and possibly other
1374 messages as well). The most 'straighforward' way of doing this is to
1375 basically simulate the main loop, but just accumulate the command text
1376 instead of sending it to execute_command(). */
1377
1378char *
1379energize_command_line_input(prompt, repeat)
1380 char *prompt;
1381 int repeat;
1382{
1383 char *p;
1384
1385 if (!energize)
1386 return command_line_input(prompt, repeat);
1387
1388 if (doing_breakcommands_message)
1389 {
1390 if (command_line_length <= 0)
1391 return (char *)NULL;
1392
1393 p = command_line_text;
1394
1395 while (command_line_length-- > 0)
1396 {
1397 if (*command_line_text == '\n')
1398 {
1399 *command_line_text = '\000';
1400 command_line_text++;
1401 break;
1402 }
1403 command_line_text++;
1404 }
1405
1406 printf_filtered("%s\n", p);
1407 return p;
1408 }
1409 else
1410 {
1411 /* We come here when the user has typed the 'command' or 'define' command
1412 to the GDB window. We are basically deep inside of the 'command'
1413 command processing routine right now, and will be called to get a new
1414 line of input. We expect that kernel_dispatch will queue up only one
1415 command at a time. */
1416
1417 int eventmask;
1418 static char buf[100];
1419
1420 eventmask = wait_for_events(0);
1421
1422 if (eventmask & PTY_EVENT)
1423 pty_to_kernel();
1424
1425 if (eventmask & KERNEL_EVENT)
1426 kernel_dispatch(1); /* Queue up commands */
1427
1428/* Note that command has been echoed by the time we get here */
1429
1430 p = dequeue_command();
1431
1432 if (p)
1433 {
1434 strncpy(buf, p, sizeof(buf));
1435 free(p);
1436 return buf;
1437 }
1438 else
1439 return NULL;
1440 }
1441}
1442\f
1443/* Establish contact with the kernel. */
1444
1445void
1446energize_initialize(energize_id, execarg)
1447 char *energize_id;
1448 char *execarg;
1449{
1450 CTtyRequest *req;
1451 char *ctmp;
1452 extern long strtol(char *str, char **ptr, int base);
1453 char pathname[MAXPATHLEN];
1454 int n;
1455
1456 if (!energize_id)
1457 return;
1458
1459 if (!execarg) execarg = "";
1460
b5fee91e
SG
1461 exec_file = strdup(execarg); /* Save for later */
1462
f823634c
SG
1463 printf("\ngdb-debugger pid=%d\n", getpid()); /* XXX - debugging only */
1464
1465 /* First establish the connection with the kernel. */
1466
1467 kerfd = COpenClientSocket(NULL);
1468 if (kerfd < 0) {
1469 printf("COpenClientSocket() failed\n");
1470 exit(1);
1471 }
1472
1473 /* Setup for I/O interrupts when appropriate. */
1474
00556177
SG
1475#ifdef NCR486
1476 if (ioctl (kerfd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
1477 perror ("getpty: ioctl I_SETSIG failed");
1478#else
f823634c
SG
1479 n = fcntl(kerfd, F_GETFL, 0);
1480 fcntl(kerfd, F_SETFL, n|FASYNC);
00556177
SG
1481 fcntl(kerfd, F_SETOWN, getpid());
1482#endif
f823634c
SG
1483
1484 /* Setup connection buffering. */
1485
1486 CSetSocketBufferSize (kerfd, 12000);
1487
1488 /* Generate a new connection control block. */
1489
1490 conn = NewConnection (0, kerfd, kerfd);
1491 if (!conn) {
1492 printf("NewConnection() failed\n");
1493 exit(1);
1494 }
1495
1496#ifdef KERNEL_RECORD
1497 kerout = fopen("kernel.output", "+w");
1498
1499 CReadWriteHooks(conn, conn->previewMethod, conn->readMethod, kernel_record);
1500#endif
1501
1502 /* Tell the kernel that we are the "debugger". */
1503
1504 req = CWriteTtyRequest (conn, QueryConnectionRType);
1505 req->generic.queryconnection.major = 0;
1506 req->generic.queryconnection.minor = 0;
1507 req->generic.queryconnection.cadillacId1=strtol(energize_id, &ctmp, 16);
1508 req->generic.queryconnection.cadillacId2 = strtol(++ctmp, NULL, 16);
1509 req->generic.queryconnection.nProtocols = 1;
1510 CWriteProtocol (conn, 0, 0, "debugger");
1511 CWriteLength (conn);
1512
1513 /* Tell the kernel that we are actually running. */
1514
1515 /* KROCK ALERT!!! The kernel doesn't really care about the arguments to
1516 the program at all! It only cares that argument 7 be the name of the
1517 target program. So, we just fill in the rest of the slots with
1518 padding. I hope the kernel never cares about this! */
1519
1520 req = CWriteTtyRequest (conn, RunningProgramRType);
1521 req->runningprogram.argc = 8;
00556177 1522 getcwd (pathname, MAXPATHLEN);
f823634c
SG
1523 CWriteVstring0 (conn, pathname);
1524
1525 CWriteVstring0 (conn, "0");
1526 CWriteVstring0 (conn, "1");
1527 CWriteVstring0 (conn, "2");
1528 CWriteVstring0 (conn, "3");
1529 CWriteVstring0 (conn, "4");
1530 CWriteVstring0 (conn, "5");
1531 CWriteVstring0 (conn, "6");
1532 CWriteVstring0 (conn, execarg);
1533 CWriteLength (conn);
1534
1535 /* Tell the kernel our PID and all that */
1536
1537 program_id = 1;
1538 CVWriteDebugProgramInfo(conn,
1539 getpid(),
1540 program_id,
1541 execarg,
1542 "");
1543
1544 /* Tell the rest of the world that Energize is now set up. */
1545 energize = 1;
1546
00556177
SG
1547 /* Drop controlling tty, become pgrp master */
1548
1549 setsid();
1550
f823634c 1551 getpty(); /* Setup the pty */
00556177
SG
1552
1553 /* Attach all GDB I/O to the pty */
1554
1555 dup2(inferior_tty, 0);
f823634c
SG
1556 dup2(inferior_tty, 1);
1557 dup2(inferior_tty, 2);
1558}
1559
1560/* This is called from execute_command, and provides a wrapper around
1561 various command routines in a place where both protocol messages and
1562 user input both flow through.
1563*/
1564
1565void
1566energize_call_command(cmdblk, arg, from_tty)
1567 struct cmd_list_element *cmdblk;
1568 char *arg;
1569 int from_tty;
1570{
1571 if (!energize)
1572 {
1573 (*cmdblk->function.cfunc) (arg, from_tty);
1574 return;
1575 }
1576
1577 if (cmdblk->class == class_run)
1578 {
1579 go_busy();
1580 has_run = 1;
1581 (*cmdblk->function.cfunc)(arg, from_tty);
1582 send_status();
1583 }
1584 else
1585 (*cmdblk->function.cfunc)(arg, from_tty);
1586
5ca812d4
SG
1587 if (strcmp(cmdblk->name, "up") == 0
1588 || strcmp(cmdblk->name, "down") == 0
1589 || strcmp(cmdblk->name, "frame") == 0)
1590 send_location(get_frame_info(selected_frame)->pc,
1591 selected_frame_level);
f823634c
SG
1592 print_prompt();
1593}
1594
1595void
1596energize_new_process()
1597{
1598 instance_id = inferior_pid;
1599}
1600
1601static void
1602iosig(signo)
1603 int signo;
1604{
1605 while (1)
1606 {
1607 int eventmask;
1608
1609 eventmask = wait_for_events(1);
1610
1611 if (eventmask == 0)
1612 return;
1613
1614 if (eventmask & PTY_EVENT)
1615 pty_to_kernel();
1616
1617 if (eventmask & KERNEL_EVENT)
1618 kernel_dispatch(1);
1619 }
1620}
1621
1622int
1623energize_wait(status)
1624 int *status;
1625{
1626 int pid;
00556177 1627 static sigset_t nullsigmask = {0};
f823634c
SG
1628
1629 if (!energize)
00556177
SG
1630#ifdef USE_PROC_FS
1631 return proc_wait (status);
1632#else
f823634c 1633 return wait(status);
00556177 1634#endif
f823634c 1635
00556177
SG
1636#ifdef NCR486
1637 action.sa_handler = iosig;
1638 action.sa_mask = nullsigmask;
1639 action.sa_flags = SA_RESTART;
1640 sigaction(SIGIO, &action, NULL);
1641#else
f823634c 1642 signal(SIGIO, iosig);
00556177 1643#endif
f823634c 1644
00556177
SG
1645#ifdef USE_PROC_FS
1646 pid = proc_wait (status);
1647#else
f823634c 1648 pid = wait(status);
00556177 1649#endif
f823634c 1650
00556177 1651 signal(SIGIO, SIG_IGN);
f823634c
SG
1652 return pid;
1653}
1654
1655static void
1656null_routine(arg)
1657 int arg;
1658{
1659}
1660
1661/* All requests from the Energize kernel eventually end up here. */
1662
1663void
1664energize_main_loop()
1665{
1666 CTtyRequest *req;
1667 struct cleanup *old_chain;
1668
1669 doing_breakcommands_message = 0;
1670
1671/* We will come thru here any time there is an error, so send status if
1672 necessary. */
1673
1674 send_status();
1675
1676 print_prompt();
1677
1678 /* The actual event loop! */
1679
1680 while (1)
1681 {
1682 int eventmask;
1683 char *cmd;
1684
1685 old_chain = make_cleanup(null_routine, 0);
1686
1687/* First, empty out the command queue, then check for new requests. */
1688
1689 while (cmd = dequeue_command())
1690 {
1691 execute_command_1(1, 0, cmd);
1692 free(cmd);
1693 }
1694
1695 eventmask = wait_for_events(0);
1696
1697 if (eventmask & PTY_EVENT)
1698 pty_to_kernel();
1699
1700 if (eventmask & KERNEL_EVENT)
1701 kernel_dispatch(0);
1702
1703 bpstat_do_actions(&stop_bpstat);
1704 do_cleanups(old_chain);
1705 }
1706}
This page took 0.094237 seconds and 4 git commands to generate.