"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,&regs) > 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,&regs) > 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,&regs) > 0)
  727                 || (re_match(output_pattern[O_EXEC_MESS_BEFORE].buf,output,strlen(output),0,&regs) > 0)
  728                 || (re_match(output_pattern[O_EXEC_GDB].buf,output,strlen(output),0,&regs) > 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