"Fossies" - the Fresh Open Source Software Archive

Member "xxgdb-1.12/gdb_handler.c" (19 Apr 1995, 24559 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_handler.c
   62  *
   63  *  WARNING : gdb_handler.c is included by handler.c for GDB.
   64  *
   65  *    Contain action handlers for the parser to invoke upon a dbx command.
   66  *
   67  *    updown_handler():     Update file, line label, updown arrow position.
   68  *    debug_handler():      Check directory use list, display main source file.
   69  *    pwd_handler():        Update current working directory.
   70  *    search_handler():     Adjust source file to display matched line.
   71  *    display_info_handler(): Update display window.
   72  *    break_handler():      Place stop sign on line or function or address specified.
   73  *    info_dir_handler():   Update search directory list. 
   74  *    directory_handler():  Update search directory list. 
   75  *    list_handler():       Adjust source file to display result. 
   76  *    info_line_handler():  Update current file. 
   77  *    delete_handler():     Remove stop sign.
   78  *    display_handler():    Update display window.
   79  *    info_break_handler(): Update stop signs.
   80  *    cd_handler():         Record current working directory.
   81  *    frame_curr_handler(): Update current function name.
   82  *    exec_handler():       Update file, line label, arrow position.
   83  *    done_handler():       Progrm execution completed, clear breakpoints
   84  *    source_handler():     Exec commands of source file specified.
   85  *    query_gdb():          Send command to gdb.
   86  */
   87 
   88 #ifdef SYSV 
   89 #   include <signal.h>
   90 #endif
   91 
   92 
   93 /*  
   94  *  Display an outlined arrow to locate the calling routine in a stack
   95  *  frame.
   96  */
   97 void updown_handler()
   98 {
   99     char *func, *file;
  100     int  line;
  101 
  102     line = Token.line;
  103     func = XtNewString(Token.func);
  104 
  105     if (line <= 0) line = 1;
  106     LoadCurrentFile();
  107     if (displayedFile)
  108     file = displayedFile->pathname;
  109     else
  110         file = NULL;                            /* AJK */
  111 
  112     if (line <= 0 || func == NULL || file == NULL)
  113         {
  114         XtFree(func);
  115         return;
  116         }
  117         
  118     if (displayedFile && strcmp(file, displayedFile->pathname)) {
  119     LoadFile(file);
  120     }
  121     updown.line = line;
  122     strcpy(updown.func, func);
  123     if (displayedFile)
  124         strcpy(updown.file, displayedFile->pathname);
  125     AdjustText(line);
  126     XtFree(func);
  127 }
  128 
  129 /* ARGSUSED */
  130 void debug_handler()
  131 {
  132     /* debug_handler is executed at start-up and with 'symbol-file' command and
  133     with 'file' command (gdb 4.0) */
  134     
  135     /* say no current compilation directory, no current source */
  136     info_source_handler(NULL,NULL,NULL);
  137     
  138     query_gdb_directories();
  139 
  140     if (new_gdb4()) /* (PW)28AUG91: test for gdb 4.0 */
  141         {
  142         /* (SH) for gdb 4.0 */
  143 #ifndef NeXT
  144         query_gdb("set height 0\n",     PARSE_OFF | ECHO_OFF | FILTER_OFF); 
  145         query_gdb("set width 0\n",      PARSE_OFF | ECHO_OFF | FILTER_OFF);
  146 #endif
  147         query_gdb("set p pretty on\n",  PARSE_OFF | ECHO_OFF | FILTER_OFF);
  148         query_gdb("set confirm off\n",  PARSE_OFF | ECHO_OFF | FILTER_OFF);
  149         }
  150     else
  151         {
  152         query_gdb("set screensize 0\n",     PARSE_OFF | ECHO_OFF | FILTER_OFF);
  153         query_gdb("set prettyprint on\n",   PARSE_OFF | ECHO_OFF | FILTER_OFF);
  154         }
  155 
  156     /* (PW)12MAR93 : the update of cwd[] is done here now. This is
  157     done by sending the 'pwd' to gdb. It is important to always use
  158     the SAME to get cwd. Sometimes the system get_cwd() and the pwd
  159     do not yield the same result. In that case, we would have problems.
  160     */
  161     query_gdb("pwd\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  162     
  163     displayedFile = NULL;       /* force reloading of source file */
  164  
  165     /* here we use FILTER_ON so that any error message will be displayed ! */
  166     /* tell gdb to use main file and get line number of main(). (,main will end at main) */
  167     
  168     query_gdb("list ,main\n", PARSE_ON | ECHO_OFF | FILTER_ON); 
  169 
  170     if (displayedFile && LoadCurrentFile() == 0)
  171         /* Only if there is a current displayedFile (pavel 4-Dec-1991) */
  172         {
  173         arrow.line = 0;         /* clear arrow sign */
  174         updown.line = 0;        /* clear updown sign */
  175         bomb.line = 0;          /* clear bomb sign */
  176         UpdateArrow(displayedFile);
  177         UpdateUpdown(displayedFile);
  178         UpdateBomb(displayedFile);
  179         ClearStops();
  180         UpdateStops(displayedFile);
  181         }
  182         
  183     UpdateMessageWindow("Ready for execution",NULL);
  184     
  185     /* clear display window */
  186     
  187     query_gdb("display\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  188 }
  189 
  190 void cd_handler(s)
  191 char *s;
  192 {
  193     strcpy(cwd,s);
  194     if (debug)
  195       fprintf(stderr,"New cwd[] is \"%s\"\n", s);
  196     CleanUpFileTable ();
  197 }
  198 
  199 void pwd_handler(s)
  200 char *s;
  201 {
  202     cd_handler((char *)strtok(s, "\n"));
  203 }
  204 
  205 void search_handler()
  206 {
  207     AdjustText(Token.line);
  208 }
  209 
  210 /*  Show output on the display window.
  211  *  If output is null but the display window is managed, replace contents of
  212  *  the display window with the null string.
  213  */
  214 void display_info_handler()
  215 {
  216     Arg     args[MAXARGS];
  217     Cardinal    n;
  218     
  219 #ifndef NEW_INTERFACE
  220 #ifdef UNDISPWIN
  221     /* this code removes the display window when there is nothing to display (GWC) */
  222     
  223     if (!Token.display || strcmp(Token.display, "") == 0) {
  224         XtUnmanageChild(separator);
  225         XtUnmanageChild(displayWindow);
  226         return;
  227     }
  228 #endif /* UNDISPWIN */
  229 #endif /* NEW_INTERFACE */
  230 
  231     if (!Token.display || strcmp(Token.display, "") == 0) {
  232 #ifndef NEW_INTERFACE
  233     if (!XtIsManaged(displayWindow))
  234         return;
  235     else {
  236 #endif
  237         XtFree(Token.display);
  238         Token.display = XtNewString("");
  239 #ifndef NEW_INTERFACE
  240     }
  241 #endif
  242     }
  243 #ifndef NEW_INTERFACE
  244     if (!XtIsManaged(displayWindow)) {
  245     XtManageChild(separator);
  246     XtManageChild(displayWindow);
  247     }
  248 #endif
  249     n = 0;
  250     XtSetArg(args[n], XtNstring, (XtArgVal) Token.display);     n++;
  251     XtSetValues(displayWindow, args, n);
  252     XtFree(Token.display);
  253     Token.display = 0;      /*(PW)14JAN91 */
  254 }
  255 
  256 /*  Place a stop sign next to the line specified on the source file window 
  257  *  if it is to be viewable.
  258  */
  259 void break_handler()
  260 {
  261 char * file;
  262 int line;
  263 int stop;
  264 
  265     if (Token.stop == 0 || Token.line == 0 || Token.file == 0)
  266     return;
  267     
  268     line = Token.line;
  269     stop = Token.stop;
  270     
  271     if (Token.stop >= 256)  /* see MAXSTOPS in signs.c */
  272         {
  273         fprintf(stderr,"Too many breakpoints\n");
  274         return;
  275         }
  276     
  277     /* load & display file if none is displayed */
  278     
  279     file = GetSourcePathname(Token.file);
  280     
  281     if (file == NULL)
  282         return;     /* (PW)11JAN91 */
  283         
  284     if (displayedFile == NULL)
  285         {
  286         LoadFile(file);
  287         AdjustText(line);
  288         }
  289         
  290     stops[stop].file = file;
  291     stops[stop].line = line;
  292     stops[stop].tag = 0;
  293     nstops = stop;
  294 
  295     /* display breakpoint sign if file is displayed */
  296     
  297     if (displayedFile)
  298         {
  299         if (!strcmp(file, displayedFile->pathname)) 
  300             DisplayStop(displayedFile, line);
  301         }
  302 }
  303 
  304 /*  info directories 
  305  */
  306 void info_dir_handler()
  307 {
  308     if (Token.file)
  309         {
  310         MakeDirList(Token.file);
  311         CleanUpFileTable ();
  312         }
  313 }
  314 
  315 /* ARGSUSED */
  316 void directory_handler()
  317 {
  318     /* Note : for GDB, the 'directory' command with no
  319     parameter will reset search directories to current 
  320     directory only. GDB requires confirmation */
  321     
  322     query_gdb_directories();
  323 }
  324 
  325 void list_handler()
  326 {
  327     int  line;
  328     
  329     line = Token.line;
  330 
  331     if (line)
  332         {
  333         /* update compilation directory (if gdb 4.0) before loading source file */
  334         if (new_gdb4())
  335             query_gdb("info source\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  336         
  337         /* We will display the last line listed. 
  338         Since we used 'list ,main' we will effectively display main in that case. */
  339 
  340         LoadCurrentFile();
  341         AdjustText(line);
  342         }
  343     else
  344         {
  345         AppendDialogText("Error list command\n");
  346         bell(0);
  347         }
  348 }
  349 
  350 /* ARGSUSED */
  351 void info_line_handler()    /* Command was 'info line' */
  352 {
  353     /* Note that CurrentFile is not run through simplify_path().
  354     This is ok because LoadFile() will do it.
  355     */
  356     
  357     if (Token.file)
  358     strcpy(CurrentFile, Token.file);
  359     else
  360     strcpy(CurrentFile, "");
  361 }
  362 
  363 /*
  364  *  Delete handler remove the stop specified and undisplayed the stopsign
  365  *  if it's visible.
  366  *  It calls the dbx status command to find out what stops are left, and
  367  *  then update the array of stops accordingly.
  368  */
  369 /* ARGSUSED */
  370 
  371 void delete_handler()
  372 {
  373     /* update breakpoints */
  374     query_gdb("info break\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  375 }
  376 
  377 void display_handler()  /* display or undisplay */
  378 {
  379     /* update display */
  380     query_gdb("display\n", PARSE_ON | ECHO_OFF | FILTER_ON);
  381 }
  382 
  383 /* 
  384 (gdb) info break
  385 Breakpoints:
  386 Num Enb   Address    Where
  387 #1   y  0x000022f4  in main (pw.c line 34)
  388 #2   y  0x000022a0  in foo (pw.c line 5)
  389 (gdb) info break
  390 No breakpoints.
  391 
  392 New for gdb 4.5 :
  393 Num Type           Disp Enb Address    What
  394 1   breakpoint     keep y   0x000022a4 in main at mem.c:9
  395 
  396 */
  397 
  398 void info_break_handler(output_string)
  399 char *output_string;
  400 {
  401 int  i; 
  402 int  line;
  403 char c;
  404 char type[20],disp[20],enb[20];
  405 
  406     if (!output_string)
  407         return;
  408         
  409     if (strncmp(output_string,"Num Type",8)) { /* Pre 4.5 */
  410     while(*output_string)
  411         {
  412         if (*(output_string++) == '#')
  413             {
  414             if (sscanf(output_string, "%d %c", &i,&c) == 2)
  415                 if (i > 0 && i <= nstops && stops[i].line > 0 && c == 'y') 
  416                     stops[i].tag = 1;
  417             }
  418         }
  419     } else { /* for 4.5 Display (Ken Mandelberg, km@mathcs.emory.edu) */
  420     while(*output_string)
  421         {
  422         if (*(output_string++) == '\n')
  423             {
  424             if (sscanf(output_string, "%d%s%s%s", &i,type,disp,enb) == 4)
  425                 if (i > 0 && i <= nstops && stops[i].line > 0 &&
  426                     !strcmp(type,"breakpoint") && !strcmp(enb,"y")) 
  427                     stops[i].tag = 1;
  428             }
  429         }
  430     }
  431         
  432     for (i=1; i<=nstops; i++)
  433     if (stops[i].line > 0)
  434         {
  435         if (stops[i].tag)
  436             stops[i].tag = 0;
  437         else 
  438             {
  439             line = stops[i].line;
  440             stops[i].line = 0;
  441             stops[i].file = NULL;
  442             if (LineToStop_no(line) == 0)
  443                 RemoveStop(line);
  444             }
  445         }
  446 }
  447 
  448 /* this handler justs update the function name.
  449 Because the function name is not always displayed
  450 after next,step ... */
  451 
  452 static char* funcname = 0;
  453 
  454 void frame_curr_handler()
  455 {
  456     if (Token.func == NULL)
  457         return;
  458         
  459     if (funcname)
  460         {
  461         XtFree(funcname);
  462         funcname = 0;
  463         }
  464         
  465     funcname = XtNewString(Token.func);
  466 }
  467 
  468 /*  Handle dbx output of run, cont, next, step, return commands.
  469  *  Result of output parsing is returned in a set of tokens.
  470  *
  471  *  If message is not 0, this is an important message and should
  472  *  be displayed instead of Token.mesg.
  473  *  This message will hold the Bus error and segmentation violation errors.
  474  *  signal is the signal number received (if any).
  475  */
  476 void exec_handler(message,signal)
  477 char *message;
  478 int signal;
  479 {
  480     int  line, status;
  481     char *func;
  482 
  483     /* Print "stopped in ..." line in message window 
  484      * Adjust text displayed
  485      */
  486     if (Token.line == 0) 
  487         return; 
  488         
  489     if (message)
  490         UpdateMessageWindow(message,NULL);
  491     else
  492         UpdateMessageWindow(Token.mesg,NULL);
  493         
  494     line = Token.line;
  495     func = (Token.func) ? XtNewString(Token.func) : 0;
  496     
  497     if (Token.file)
  498     status = LoadFile(Token.file);
  499     else
  500         status = -1;                           /* AJK */
  501     
  502     display_info_handler();     /* uses Token.display ! */
  503 
  504     /* because of tbreak, we have to call info break here */
  505     
  506      query_gdb("info break\n", PARSE_ON | ECHO_OFF | FILTER_OFF); /* update breakpoints */
  507 
  508     if (func == NULL)
  509         {
  510         /* because silly gdb 4.0 displays nothing with frame command when
  511         confirm is on (possibly a gdb bug) , I just reset confirm to on
  512         just for this command !. */
  513         
  514         if (new_gdb4()) 
  515             query_gdb("set confirm on\n",   PARSE_OFF | ECHO_OFF | FILTER_OFF);
  516             
  517         /* this will just update funcname (see frame_curr_handler()) */
  518         query_gdb("frame\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  519         
  520         if (new_gdb4()) /* reset confirm to off */
  521             query_gdb("set confirm off\n",  PARSE_OFF | ECHO_OFF | FILTER_OFF);
  522             
  523         func = funcname;
  524         if (func == NULL)
  525             return;
  526         funcname = 0;   /* tell frame_curr_handler WE are going to XtFree it */
  527         }
  528         
  529     arrow.line = line;          /* update arrow sign position */
  530     strcpy(arrow.func, func);
  531     
  532     updown.line = 0;            /* remove updown, if any */
  533     if (displayedFile) {
  534         strcpy(arrow.file, displayedFile->pathname);
  535     }
  536     
  537     /* Display bomb sign if segmentation fault occurs in source code */
  538     
  539     if (status != -1 && message && signal == SIGSEGV) {
  540     arrow.line = 0;
  541     bomb.line = line;
  542     if (func)
  543     strcpy(bomb.func, func);
  544     if (displayedFile) strcpy(bomb.file, displayedFile->pathname);
  545     }
  546     else
  547     bomb.line = 0;
  548 
  549     AdjustText(line);
  550     XtFree(func);
  551 }
  552 
  553 /*  Remove all the arrow and updown signs, print message, then 
  554  *  change the file variable to the file name displayed.
  555  */
  556 /* ARGSUSED */
  557 void done_handler(message,signal)
  558 char *message;
  559 int signal;
  560 {
  561     arrow.line = 0;
  562     updown.line = 0;
  563     UpdateArrow(displayedFile);
  564     UpdateUpdown(displayedFile);
  565     UpdateMessageWindow("Ready for execution",NULL);
  566 }
  567 
  568 /*--------------------------------------------------------------------------+
  569 |                                                                           |
  570 |   Function to read the .gdbinit file or any source file.                  |
  571 |                                                                           |
  572 |   input : file name.                                                      |
  573 |                                                                           |
  574 |   output : none.                                                          |
  575 |                                                                           |
  576 +--------------------------------------------------------------------------*/
  577 void read_source_file(file)
  578 char *file;
  579 {
  580 char s[LINESIZ];
  581 FILE *fp;
  582 
  583     if ((fp = fopen(file, "r")))
  584         {
  585         while (fgets(s, LINESIZ, fp))
  586             {
  587             /* Check for comment line,
  588                 DO NOT SEND '\n',
  589                 Take care of source command,
  590                 Take care of define or document commands.
  591             */
  592             
  593             if ((*s != '#') && strcmp(s,"\n"))  
  594                 {
  595                 if (!(gdb_source_command (s,TRUE)
  596                         || gdb_define_command (s,fp)
  597                         || xxgdb_command (s,TRUE)))
  598                     
  599                     /* send to gdb only if it is not source, define or an
  600                     xxgdb command.
  601                     */
  602                     query_gdb(s, PARSE_ON | ECHO_ON | FILTER_ON);
  603                 }
  604             }
  605             
  606         fclose(fp);
  607         }
  608 }
  609 
  610 /* WARNING : source_handler() is NOT called by the parser.
  611 It is called by gdb_source_command() in gdb_parser.c.
  612 This is because 'source' command is NEVER sent to gdb,
  613 instead xxgdb sends the commands in the specified file
  614 one by one. */
  615 
  616 void source_handler()
  617 {
  618 char *file;
  619 
  620     if (!Token.file || strcmp(Token.file, "") == 0)
  621         {
  622         XtFree(Token.file);
  623         Token.file = XtNewString(gdbinit);      /* default is .gdbinit */
  624         }
  625         
  626     file = GetPathname(Token.file);
  627     
  628     if (file == NULL) {
  629         /* error message already displayed by GetPathname() */
  630         return;     /* (PW)11JAN91 */
  631     }
  632 
  633     read_source_file(file);
  634 }
  635 
  636 /*  core-file  
  637  *  gdb does not display current line, file, func ..., so we send
  638  *  'frame 0' command to have them.
  639  */
  640 void core_file_handler()
  641 {
  642     char *message;
  643     int line;
  644     int signal;
  645     
  646     message = XtNewString(Token.mesg);
  647     signal = Token.stop;                    /* signal number received */
  648     
  649     /* because silly gdb 4.0 displays nothing with frame command when
  650     confirm is on (possibly a gdb bug) , I just reset confirm to on
  651     just for this command !. */
  652 
  653     if (new_gdb4()) 
  654         query_gdb("set confirm on\n",   PARSE_OFF | ECHO_OFF | FILTER_OFF);
  655 
  656     /* this will update updown.line, updown.func and updown.file.
  657     (see updown_handler) */
  658     query_gdb("frame 0\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  659     
  660     if (new_gdb4()) /* reset confirm to off */
  661         query_gdb("set confirm off\n",  PARSE_OFF | ECHO_OFF | FILTER_OFF);
  662 
  663     line = updown.line;
  664     updown.line = 0;
  665     
  666     /* Display bomb sign if segmentation fault occurred in source code */
  667     
  668     if (line != 0 && signal == SIGSEGV) {
  669     arrow.line = 0;
  670     bomb.line = line;
  671     strcpy(bomb.func, updown.func);
  672     strcpy(bomb.file, updown.file);
  673     } else {
  674     bomb.line = 0;
  675     arrow.line = line;
  676     strcpy(arrow.func, updown.func);
  677     strcpy(arrow.file, updown.file);
  678     }
  679     
  680     UpdateMessageWindow(message,NULL);
  681     XtFree(message);
  682     AdjustText(line); 
  683 }
  684 
  685 /*--------------------------------------------------------------------------+
  686 |                                                                           |
  687 |   Function to get the current source path directories.                    |
  688 |                                                                           |
  689 |    WARNING : this function is called at startup of xxgdb                  |
  690 |    to test for gdb 4.0 or earlier versions.                               |
  691 |    The 1st time that query_gdb_directories() is called,                   |
  692 |    new_gdb is true, and 'show directories' command is                     |
  693 |    issued to gdb. Then parse() in gdb_parser.c will test for              |
  694 |    'show Unknown command' answer from gdb, and in that case               |
  695 |    will set new_gdb to false. See show_is_undefined() below.              |
  696 |                                                                           |
  697 +--------------------------------------------------------------------------*/
  698 void query_gdb_directories()
  699 {
  700     if (new_gdb4()) /* (PW)28AUG91: test for gdb 4.0 */
  701         query_gdb("show directories\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  702     else
  703         query_gdb("info directories\n", PARSE_ON | ECHO_OFF | FILTER_OFF);
  704 }
  705 
  706 /*--------------------------------------------------------------------------+
  707 |                                                                           |
  708 |   Function to know if we are running the NEW gdb                          |
  709 |                                                                           |
  710 |   return TRUE if we are running gdb 4.0 (or 3.9x or higher)               |
  711 |                                                                           |
  712 |   WARNING : it is important that the default is gdb 4.0.                  |
  713 |             (see comments on query_gdb_directories() above).              |
  714 |                                                                           |
  715 |   (PW)(DS)19FEB92 NeXT :                                                  |
  716 |   gdb 3.1 for the NeXT OS 2.1 does not answer 'undefined command' when    |
  717 |   trying to execute 'show'. That is why the test for gdb-4.x vs           |
  718 |   gdb 3.x does not work in case of NeXT. Using gdb 3.x as default         |
  719 |   will make xxgdb skip this test.                                         |
  720 |   The gdb answer is "Ambiguous command "show": shownops, showps.".        |
  721 |                                                                           |
  722 +--------------------------------------------------------------------------*/
  723 #if defined(NeXT) && defined(NEXTOS_2)
  724 static int new_gdb = False;         /* special case for NeXT */
  725 #else
  726 static int new_gdb = True;          /* default : we are running gdb 4.0 */
  727 #endif
  728 
  729 int new_gdb4()
  730 {
  731     return new_gdb;
  732 }
  733 
  734 /*--------------------------------------------------------------------------+
  735 |                                                                           |
  736 |   Function to say that 'show' command is undefined and thus               |
  737 |   that we are running an old version of gdb.                              |
  738 |                                                                           |
  739 +--------------------------------------------------------------------------*/
  740 void show_is_undefined()
  741 {
  742     new_gdb = False;
  743 }
  744 
  745 /*--------------------------------------------------------------------------+
  746 |                                                                           |
  747 |   Update compilation directory                                            |
  748 |                                                                           |
  749 |   This function is used for gdb 4.0 which uses the compilation            |
  750 |   directory in the source path.                                           |
  751 |                                                                           |
  752 |   input : current compilation directory,                                  |
  753 |           current source full path,                                       |
  754 |           current source path.                                            |
  755 |       (returned from 'info source' gdb command).                          |
  756 |                                                                           |
  757 |   output : none.                                                          |
  758 |                                                                           |
  759 +--------------------------------------------------------------------------*/
  760 char cdir[MAXPATHLEN];              /* The compilation directory */
  761 char source_fullpath[MAXPATHLEN];   /* The current source file full path  */
  762 char source_path[MAXPATHLEN];       /* The current source file name  */
  763 
  764 void
  765 info_source_handler(compile_dir,current_source_path, current_source)
  766 char * compile_dir;
  767 char * current_source_path;
  768 char * current_source;
  769 {
  770     cdir[0] = 0;
  771     if (compile_dir != NULL)
  772         {
  773         simplify_path (compile_dir);  /* be sure to get only significant path */
  774 
  775         if (strlen (compile_dir) < MAXPATHLEN)      /* check length */
  776             strcpy (cdir, compile_dir);
  777         else
  778             UpdateMessageWindow("Path too long \"%s\"", compile_dir);
  779         
  780         if (LASTCH(cdir) == '/')                    /* remove last '/' */
  781             LASTCH(cdir) = '\0';
  782     }
  783 
  784     source_fullpath[0] = 0;
  785     if (current_source_path != NULL)
  786         {
  787         simplify_path (current_source_path);  /* be sure to get only significant path */
  788 
  789         if (strlen (current_source_path) < MAXPATHLEN)      /* check length */
  790             strcpy (source_fullpath, current_source_path);
  791         else
  792             UpdateMessageWindow("Path too long  \"%s\"", current_source_path);
  793         }
  794 
  795     source_path[0] = 0;
  796     if (current_source != NULL)
  797         {
  798         simplify_path (current_source);  /* be sure to get only significant path */
  799 
  800         if (strlen (current_source) < MAXPATHLEN)       /* check length */
  801             strcpy (source_path, current_source);
  802         else
  803             UpdateMessageWindow("Path too long  \"%s\"", current_source);
  804         }
  805 
  806     if (debug)
  807           fprintf(stderr,"cdir = \"%s\"\nsource = \"%s\"\nsource full path = \"%s\"\n",
  808             cdir, source_path, source_fullpath);
  809 }
  810 
  811 /*--------------------------------------------------------------------------+
  812 |                                                                           |
  813 |   Function to simplify a pathname :                                       |
  814 |                                                                           |
  815 |       /.              =>      /                                           |
  816 |       /./xxx          =>      /xxx                                        |
  817 |       /foo/..         =>      /                                           |
  818 |       /foo/../xxx     =>      /xxx                                        |
  819 |       foo/..          =>      .                                           |
  820 |       foo/../         =>      .                                           |
  821 |       foo/../xxx      =>      xxx                                         |
  822 |       xxx/            =>      xxx                                         |
  823 |                                                                           |
  824 +--------------------------------------------------------------------------*/
  825 void
  826 simplify_path(path)
  827 char *path;
  828 {
  829 char *p;
  830 int len;
  831 
  832     for (p = path; *p;)
  833         {
  834         if (!strncmp (p, "/./", 2)
  835             && (p[2] == 0 || p[2] == '/'))
  836             {
  837             if (p[2] == 0 && p == path)     /* '/.' => '/' */
  838                 *(p+1) = 0;                 /* keep first '/' */
  839             else
  840                 strcpy (p, p + 2);          /* '/./xxx' => '/xxx' */
  841             }
  842         else
  843             if (!strncmp (p, "/..", 3)
  844                 && (p[3] == 0 || p[3] == '/')
  845                 && p != path)
  846                 {
  847                 char *q = p;
  848                 
  849                 /* search previous '/' */
  850                 while (q != path && q[-1] != '/') q--;
  851                 
  852                 if (q != path)  /* previous '/' was found */
  853                     {
  854                     if (p[3] == 0 && (q-1) == path) /* '/foo/..'=> '/' */
  855                         *q = 0;                     /* keep first '/'  */
  856                     else
  857                         strcpy (q-1, p+3);      /* '/foo/../xxx' => '/xxx' */
  858                     p = q-1;
  859                     }
  860                 else    /* previous '/' was not found */
  861                     {                            /* 'foo/..'  => '.' */
  862                     if (p[3] == 0 || p[4] == 0)  /* 'foo/../' => '.' */
  863                         strcpy (path, ".");
  864                     else                        /* 'foo/../xxx'=> xxx */
  865                         strcpy (path, p+4);
  866                     }
  867                 }
  868             else
  869                 p++;
  870         }
  871         
  872     /* remove last '/' if not in first position */
  873     
  874     len = strlen(path);
  875     if ((len > 1) && (path[len-1] == '/'))
  876         path[len-1] = 0;
  877 }
  878 
  879 
  880