"Fossies" - the Fresh Open Source Software Archive

Member "xxgdb-1.12/datadpy.c" (29 Apr 1994, 29957 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 /*  dataDpy.c:
   62  *
   63  *   Provide graphical display of C pointers and structures.
   64  *
   65  *   BuildLinePos():    Construct an array indexing the character position of 
   66  *          each line.
   67  *   PositionToLine():  Return the character position of a given line.   
   68  *   SelectPointer():   Action proc for double click on a pointer value,
   69  *   CreateDataPopup(): Create a popup to display the object pointed to by a
   70  *          pointer.
   71  *   UpdateDataPopup(): Update an unused popupshell to display data.
   72  *   AppendList():  Append a popup to the list.
   73  *   DeleteList():  Delete a popup from the list.
   74  *   pop_down():    pop down the popup and free storage.
   75  *   DestroyDataPopup():event handler for destroying a popup, call DeleteList()
   76  *          and pop_down() (CRL mod 25)
   77  *   MovePopup():   Position the popup.
   78  *   print_handler():   Action handler for displaying pointers and structures.
   79  */
   80 
   81 /*
   82  * 01FEB94: bugs fixed (klamer)
   83  *      xxgdb does not allow the graphically displaying of members of parents
   84  *          from a class.
   85  *      xxgdb does not allow the graphically displaying of data through a
   86  *         reference.
   87  */
   88 
   89 #include <string.h>
   90 #include    "global.h"
   91 #include    "regex.h"
   92 #include    "datadpy.h"
   93 
   94 #define     MAXLEVELS   20  /* max level of indentation */
   95 #ifdef GDB
   96 #define     INDENT      2   /* # of spaces for each indentation */
   97 #else
   98 #define     INDENT      8   /* # of spaces for each indentation */
   99 #endif /* GDB */
  100 #define     EMPTY           0
  101 #define     UNUSED          1
  102 #define     USED            2
  103 #define     LEFT_MARGIN 10
  104 #define     SCROLLBAR_WIDTH 15
  105 
  106 
  107 static DataDpyRec   **dataDpyTable;
  108 static int      dataDpyTableSize = 0;
  109 static DataDpyRec   *Parent = NULL;
  110 static DataDpyList  *TopParentList = NULL;
  111 static int      font_height, font_width;
  112 
  113 #ifdef OBSOLETE
  114 static void     DestroyDataPopup();
  115 #else
  116 /* CRL mod 25 4/12/91 GWC - changed label widget to command widget in popups */
  117 static void     DestroyDataCallback();
  118 #endif
  119 
  120 /* 
  121  *  Build an array which gives the starting text position of each line.
  122  *  Very similar to the routine in source.c.
  123  */
  124 static void BuildLinePos(dataDpy)
  125 DataDpyRec *dataDpy;
  126 {
  127     char *p;
  128     int  line, nlines;
  129     int  max=0;
  130 
  131     nlines = MAX(1, dataDpy->buflen/CHARS_PER_LINE);
  132     dataDpy->linepos = (XawTextPosition *)
  133                     XtMalloc ((nlines+2) * sizeof(XawTextPosition));
  134     p = dataDpy->buf;
  135     line = 0;
  136     dataDpy->linepos[line++] = 0;
  137     dataDpy->linepos[line++] = 0;
  138     while (*p) {
  139         if (*p++ == '\n') {
  140             if (line == nlines) {       /* buffer full, need more memory */
  141                 dataDpy->linepos = (XawTextPosition *)XtRealloc( (void*)dataDpy->linepos,
  142                           (nlines + ADD_LINES) * sizeof(XawTextPosition));
  143                 nlines += ADD_LINES;
  144             }
  145             dataDpy->linepos[line] = p - dataDpy->buf;
  146         AssignMax(max, dataDpy->linepos[line] - dataDpy->linepos[line-1]);
  147         line++;
  148         }
  149     }
  150     dataDpy->numlines = line - 2;
  151     dataDpy->maxLineLength = max;
  152     /* shrink to min size */
  153     dataDpy->linepos = (XawTextPosition *) XtRealloc     
  154                         ((void*)dataDpy->linepos, line * sizeof(XawTextPosition));
  155 }
  156 
  157 /*
  158  *  Return the line number for the specified text position.
  159  */
  160 static int PositionToLine(dataDpy, pos)
  161 DataDpyRec *dataDpy;
  162 XawTextPosition pos;
  163 {
  164     int  line;
  165 
  166     if (dataDpy && pos >= 0) {
  167         for (line = 1; pos >= dataDpy->linepos[line]; line++);
  168         return (line-1);
  169     }
  170     else
  171     return (0);
  172 }
  173 
  174 /* ARGSUSED */
  175 /*  
  176  *  Called by double click of pointer button.
  177  *  If the selected text is a valid pointer, this routine parses the data 
  178  *  output to obtain the full qualified name of the pointer, and asks
  179  *  dbx to print the value of the object the pointer is pointing to.
  180  */
  181 static void SelectPointer(w, event, params, num_params)
  182     Widget w;
  183     XEvent *event;
  184     String *params;
  185     Cardinal *num_params;
  186 {
  187 #ifndef GDB
  188     struct re_registers regs;
  189     char *field[MAXLEVELS];
  190     int line, n, r, level, newlevel;
  191     char        name[LINESIZ];
  192 #endif
  193     XawTextPosition     left, right;
  194     char        *selection, *p;
  195     DataDpyRec      *dataDpy;
  196     int         fromLine;
  197     int         i, nbytes;
  198     char        command[LINESIZ];
  199 
  200     /* Find out which data display output does the selection belong to */
  201     dataDpy = NULL;
  202     for (i=0; dataDpyTable[i]; i++)
  203     if ((Widget) w == (Widget) dataDpyTable[i]->dataDpyWindow) {
  204         dataDpy = dataDpyTable[i];
  205         Parent = dataDpy;
  206         break;
  207     }
  208     if (!dataDpy) return;
  209 
  210     /* Get the selection and check if it's a pointer value, 0x???? */
  211     selection = XFetchBytes(display, &nbytes);
  212     if (re_match(dataPattern[D_POINTER].buf, selection, strlen(selection), 0, 0)
  213     < 0) {
  214     Parent = NULL;
  215     return;
  216     }
  217 
  218     /* Parse the output to get the fully qualified name of the pointer */
  219     XawTextGetSelectionPos(w, &left, &right);
  220     fromLine = PositionToLine(dataDpy, left);
  221     p = dataDpy->buf + dataDpy->linepos[fromLine];
  222 
  223 #ifdef GDB  /* (PW)  we now use a new parser which should work better,
  224     in particular for arrays */
  225     {
  226     char *parse_gdb_print();
  227     char *newcommand;
  228     
  229     newcommand = parse_gdb_print(command, dataDpy->buf, dataDpy->buf + left );
  230     if (*newcommand)
  231         {
  232         if (strchr(selection, '@'))
  233         {   
  234             char    *p = strchr(newcommand, '*');
  235             if (p != 0)
  236                 *p = ' ';
  237         }
  238         PopupMode = True;
  239         query_gdb(newcommand, PARSE_ON | ECHO_OFF | FILTER_OFF);
  240         }
  241     }
  242 #else   /* not GDB */
  243 
  244     if (re_match(dataPattern[D_FIELD].buf, p, strlen(p), 0, &regs) >= 0) {
  245     r = dataPattern[D_FIELD].reg_token[TK_POINTER];
  246     if (strncmp(selection, p+regs.start[r], regs.end[r]-regs.start[r]))
  247         return;
  248     r = dataPattern[D_FIELD].reg_token[TK_INDENT];
  249     level = regs.end[r]/INDENT;
  250     field[level+1] = NULL;
  251 
  252     r = dataPattern[D_FIELD].reg_token[TK_FIELD];
  253     n = regs.end[r] - regs.start[r];
  254     field[level] = (char *) XtMalloc ((n+1) * sizeof(char));
  255     strncpy(field[level], p+regs.start[r], n);
  256     field[level][n] = '\0';
  257 
  258     for (line = fromLine-1; line > 0; line--) {
  259         p = dataDpy->buf + dataDpy->linepos[line];
  260         if (re_match(dataPattern[D_STRUCT].buf, p, strlen(p), 0, &regs)>=0){
  261         r = dataPattern[D_STRUCT].reg_token[TK_INDENT];
  262         newlevel = regs.end[r]/INDENT;
  263         if (newlevel == level-1) {
  264             level--;
  265             r = dataPattern[D_STRUCT].reg_token[TK_FIELD];
  266             n = regs.end[r] - regs.start[r];
  267             field[level] = (char *) XtMalloc ((n+1) * sizeof(char));
  268             strncpy(field[level], p+regs.start[r], n);
  269             field[level][n] = '\0';
  270         }
  271         }
  272     }
  273     if (*field[0] == '*' && field[1])
  274         sprintf(name, "(%s)", field[0]+1);
  275     else
  276         strcpy(name, field[0]);
  277         
  278     for (i=1; field[i]; i++) {
  279         strcat(name, ".");
  280         strcat(name, field[i]);
  281     }
  282     sprintf(command, "print *(%s)\n", name);
  283     PopupMode = True;
  284 #ifdef GDB
  285     query_gdb(command, PARSE_ON | ECHO_OFF | FILTER_OFF);
  286 #else
  287     query_dbx(command);
  288 #endif  /* GDB */
  289     }
  290 #endif /* GDB */
  291 }
  292 
  293     
  294 /*
  295  *  Create a data display with a label.
  296  *  The popupshell has a form widget which consists of a label and a text
  297  *  widget.
  298  */
  299 static void CreateDataPopup(dataDpy, label)
  300 DataDpyRec *dataDpy;
  301 char       *label;
  302 {
  303     Arg         args[MAXARGS];
  304     Cardinal    n;
  305     Dimension   dataDpyHeight, dataDpyWidth;
  306     XFontStruct *text_font;
  307 
  308     static XtActionsRec datadpy_actions[] = {
  309         {"SelectPointer", (XtActionProc) SelectPointer},
  310         {NULL, NULL}
  311     };
  312 
  313     static String translations = "#override \n\
  314         <Btn1Down>:     SelectStart() SelectWord() SelectPointer() \n\
  315         <Btn1Up>:       SelectEnd() \n\
  316     ";
  317 
  318     n = 0;
  319     dataDpy->popupshell = XtCreatePopupShell("Data Popup", 
  320     transientShellWidgetClass, toplevel, args, n);
  321 
  322     n = 0;
  323     XtSetArg(args[n], XtNdefaultDistance, 0);                           n++;
  324     dataDpy->popup = XtCreateManagedWidget("popup", formWidgetClass,
  325     dataDpy->popupshell, args, n);
  326 
  327     /* Create the label */
  328     n = 0;
  329     XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop);                  n++;
  330     XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainTop);               n++;
  331     XtSetArg(args[n], XtNright, (XtArgVal) XawChainRight);              n++;
  332     XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft);                n++;
  333     XtSetArg(args[n], XtNlabel, (XtArgVal) label);                      n++;
  334     XtSetArg(args[n], XtNresize, (XtArgVal) False);                     n++;
  335     XtSetArg(args[n], XtNjustify, (XtArgVal) XtJustifyCenter);          n++;
  336 
  337 #ifdef OBSOLETE
  338     dataDpy->label = XtCreateManagedWidget("label", labelWidgetClass, 
  339     dataDpy->popup, args, n);
  340 /*  GWC says it is better to use ButtonReleaseMask instead of ButtonPressMask.*/
  341     XtAddEventHandler(dataDpy->label, (EventMask) ButtonPressMask, False, 
  342     DestroyDataPopup, dataDpy);
  343 #else
  344 /* CRL mod 25 4/12/91 GWC - changed label widget to command widget in
  345 popups */
  346     dataDpy->label = XtCreateManagedWidget("command", commandWidgetClass, 
  347         dataDpy->popup, args, n);
  348     XtAddCallback(dataDpy->label, XtNcallback, DestroyDataCallback, dataDpy);
  349 #endif
  350 
  351     /* Create the text window */
  352     n = 0;
  353     XtSetArg(args[n], XtNfromVert, (XtArgVal) dataDpy->label);          n++;
  354     XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop);                  n++;
  355     XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainBottom);            n++;
  356     XtSetArg(args[n], XtNright, (XtArgVal) XawChainRight);              n++;
  357     XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft);                n++;
  358 
  359     XtSetArg(args[n], XtNleftMargin, (XtArgVal) LEFT_MARGIN);       n++;
  360     XtSetArg(args[n], XtNuseStringInPlace, (XtArgVal) True);        n++;
  361     XtSetArg(args[n], XtNstring, (XtArgVal) dataDpy->buf);              n++;
  362     XtSetArg(args[n], XtNlength, (XtArgVal) dataDpy->buflen);       n++;
  363     XtSetArg(args[n], XtNeditType, (XtArgVal) XawtextRead);             n++;
  364     XtSetArg(args[n], XtNscrollHorizontal, XawtextScrollWhenNeeded);    n++;
  365     XtSetArg(args[n], XtNscrollVertical, XawtextScrollWhenNeeded);  n++;
  366     XtSetArg(args[n], XtNtranslations, XtParseTranslationTable(translations));
  367                                                                         n++;
  368     dataDpy->dataDpyWindow = XtCreateManagedWidget("dataDpyWindow", 
  369     asciiTextWidgetClass, dataDpy->popup, args, n);
  370     XtAppAddActions(app_context, datadpy_actions, XtNumber(datadpy_actions));
  371 
  372     /* Get the text font */
  373     n = 0;
  374     XtSetArg(args[n], XtNfont, &text_font);                         n++;
  375     XtGetValues(dataDpy->dataDpyWindow, args, n);
  376 
  377     /* Estimate the size of the text widget, dataDpyWindow, with the number
  378        of lines and the maximum length of a line.  Assume fixed font width.
  379     */
  380     font_height = text_font->ascent + text_font->descent;
  381     font_width = text_font->max_bounds.width;
  382     dataDpyHeight = dataDpy->numlines * font_height + 5;
  383     dataDpyWidth = dataDpy->maxLineLength * font_width + LEFT_MARGIN;
  384     if (dataDpyHeight > app_resources.dataDpyMaxHeight)
  385     dataDpyWidth += SCROLLBAR_WIDTH;
  386     
  387 #if 1   /*(PW)17DEC90 : bug ! */
  388 #define     SCROLLBAR_HEIGHT    15
  389     if (dataDpyWidth > app_resources.dataDpyMaxWidth)
  390     dataDpyHeight += SCROLLBAR_HEIGHT;
  391 #endif
  392 
  393     AssignMin(dataDpyHeight, app_resources.dataDpyMaxHeight);
  394     AssignMin(dataDpyWidth, app_resources.dataDpyMaxWidth);
  395         
  396     n = 0;
  397     XtSetArg(args[n], XtNheight, (XtArgVal) dataDpyHeight);         n++;
  398     XtSetArg(args[n], XtNwidth, (XtArgVal) dataDpyWidth);       n++;
  399     XtSetValues(dataDpy->dataDpyWindow, args, n);
  400 
  401     n = 0;
  402     XtSetArg(args[n], XtNwidth, (XtArgVal) dataDpyWidth);       n++;
  403     XtSetValues(dataDpy->label, args, n);
  404 }
  405 
  406 /*
  407  *  Instead of creating a new popupshell, this routine uses an already
  408  *  existing popupshell for data display.
  409  *  It changes the label, calculates the size of the popupshell,
  410  *  and sets the source of the text window to that of the new data.
  411  */
  412 static void UpdateDataPopup(dataDpy, label)
  413 DataDpyRec *dataDpy;
  414 char       *label;
  415 {
  416     Arg args[MAXARGS];
  417     Cardinal n;
  418     Dimension   popupHeight, popupWidth, dataDpyHeight, dataDpyWidth,
  419         labelHeight, labelBorderWidth, dataDpyBorderWidth;
  420 
  421     /* Update the label */
  422     n = 0;
  423     XtSetArg(args[n], XtNlabel, (XtArgVal) label);                      n++;
  424     XtSetValues(dataDpy->label, args, n);
  425 
  426     /* Calculate the size of popupshell */
  427     dataDpyHeight = dataDpy->numlines * font_height + 5;
  428     dataDpyWidth = dataDpy->maxLineLength * font_width + 2*10;
  429     
  430 #if 1   /*(PW)18DEC90 : bug ! */
  431     if (dataDpyHeight > app_resources.dataDpyMaxHeight)
  432     dataDpyWidth += SCROLLBAR_WIDTH;
  433     
  434     if (dataDpyWidth > app_resources.dataDpyMaxWidth)
  435     dataDpyHeight += SCROLLBAR_HEIGHT;
  436 #endif
  437 
  438     AssignMin(dataDpyHeight, app_resources.dataDpyMaxHeight);
  439     AssignMin(dataDpyWidth, app_resources.dataDpyMaxWidth);
  440 
  441     n = 0;
  442     XtSetArg(args[n], XtNheight, (XtArgVal) &labelHeight);      n++;
  443     XtSetArg(args[n], XtNborderWidth, (XtArgVal) &labelBorderWidth);    n++;
  444     XtGetValues(dataDpy->label, args, n);
  445     n = 0;
  446     XtSetArg(args[n], XtNborderWidth, (XtArgVal) &dataDpyBorderWidth);  n++;
  447     XtGetValues(dataDpy->dataDpyWindow, args, n);
  448 
  449     popupHeight = dataDpyHeight + labelHeight + 2*labelBorderWidth +
  450           2*dataDpyBorderWidth;
  451     popupWidth = dataDpyWidth;
  452     
  453     n = 0;
  454     XtSetArg(args[n], XtNheight, (XtArgVal) popupHeight);       n++;
  455     XtSetArg(args[n], XtNwidth, (XtArgVal) popupWidth);         n++;
  456     XtSetValues(dataDpy->popupshell, args, n);
  457 
  458     /* Set the text source */
  459     n = 0;
  460     XtSetArg(args[n], XtNstring, (XtArgVal) dataDpy->buf);      n++;
  461     XtSetArg(args[n], XtNlength, (XtArgVal) dataDpy->buflen);           n++;
  462     XawTextSetSource(dataDpy->dataDpyWindow, 
  463              XtCreateWidget("textsrc", asciiSrcObjectClass, 
  464                     dataDpy->dataDpyWindow, args, n),
  465              0);
  466 }
  467 
  468 /*
  469  *  Append dataDpy to a DataDpyList pointed to by head.
  470  */
  471 static void AppendList(head, dataDpy)
  472 DataDpyList **head;
  473 DataDpyRec  *dataDpy;
  474 {
  475     DataDpyList *p, *q, *r;
  476 
  477     p = (DataDpyList *) XtNew (DataDpyList);
  478     p->dataDpy = dataDpy;
  479     p->next = NULL;
  480     q = *head;
  481     if (!q)
  482     *head = p;
  483     else {
  484     while ((r = q->next))
  485         q = r;
  486     q->next = p;
  487     }
  488 }
  489 
  490 /*
  491  *  Removes a dataDpy from its parent's list of children.
  492  */
  493 static void DeleteList(head, dataDpy)
  494 DataDpyList **head;
  495 DataDpyRec  *dataDpy;
  496 {
  497     DataDpyList *p, *q;
  498 
  499     if ((p = *head)) {
  500     if (p->dataDpy == dataDpy)
  501         *head = p->next;
  502     else {
  503         for (q = p->next; q && q->dataDpy != dataDpy;) {
  504         p = q; 
  505         q = p->next;
  506         }
  507         if (q) p->next = q->next;
  508     }
  509     }
  510 }
  511         
  512 /*
  513  *  Pop down a dataDpy and all its descendants, freeing storage and
  514  *  reinitializing fields.
  515  */
  516 static void pop_down(dataDpy)
  517 DataDpyRec *dataDpy;
  518 {
  519     DataDpyList *p, *q;
  520 
  521     XtPopdown(dataDpy->popupshell);
  522     XtFree((void*)dataDpy->linepos);
  523     XtFree(dataDpy->buf);
  524     dataDpy->buf = NULL;
  525     dataDpy->buflen = 0;
  526     dataDpy->linepos = NULL;
  527     dataDpy->state = UNUSED; 
  528     dataDpy->parent = NULL; 
  529     for (p = dataDpy->childlist; p;) {
  530     pop_down(p->dataDpy);
  531     q = p;
  532     p = p->next;
  533     XtFree((void*)q);
  534     }
  535     dataDpy->childlist = NULL;
  536 }
  537 
  538 /*
  539  *  Invoked by a ButtonPress event on the label of a data display to
  540  *  pop down itself and its descendants.
  541  */
  542 /* ARGSUSED */
  543 
  544 #ifdef OBSOLETE
  545 static void DestroyDataPopup(w, dataDpy, event)
  546     Widget w;
  547     DataDpyRec *dataDpy;
  548     XEvent *event;
  549 #else
  550 /* CRL mod 25 4/12/91 GWC - changed label widget to command widget */
  551 static void DestroyDataCallback(w, dataDpy, call_data)
  552     Widget w;
  553     DataDpyRec *dataDpy;
  554     caddr_t call_data;
  555 #endif
  556 {
  557     if (!dataDpy->parent)
  558         DeleteList(&TopParentList, dataDpy);
  559     else
  560         DeleteList(&dataDpy->parent->childlist, dataDpy);
  561     pop_down(dataDpy);
  562 }
  563 
  564 /*
  565  *  Position the data display on the screen to reflect the parent-child
  566  *  relationship.
  567  */
  568 static void MovePopup(dataDpy)
  569 DataDpyRec *dataDpy;
  570 {
  571     Arg         args[MAXARGS];
  572     Cardinal    n;
  573     Screen  *screen;
  574     int     popupHeight, popupWidth, screenHeight, screenWidth;
  575     Position    x, y;
  576     Dimension   dataDpyWidth, dataDpyHeight, dataDpyBorderWidth, 
  577         labelHeight, labelBorderWidth, width, height, borderWidth;
  578     DataDpyList *p, *q;
  579 
  580     Parent = NULL;
  581     if (!dataDpy->parent)
  582     p = TopParentList;
  583     else
  584     p = dataDpy->parent->childlist;
  585 
  586     /*  Look for its previous sibling  */
  587     for (q = p->next; q && q->dataDpy != dataDpy;) {
  588     p = q;
  589     q = q->next;
  590     }
  591     /*  If a sibling exists, place the new popup right next to it  */
  592     if (q) {
  593     n = 0;
  594     XtSetArg(args[n], XtNwidth, (XtArgVal) &width);             n++;
  595     XtSetArg(args[n], XtNborderWidth, (XtArgVal) &borderWidth); n++;
  596     XtGetValues(p->dataDpy->popupshell, args, n);
  597     XtTranslateCoords(p->dataDpy->popupshell, 0, 0, &x, &y);
  598     x += width;
  599     y -= borderWidth;
  600     }
  601     else {  /* no siblings */
  602     /*  this is the very first popup  */
  603     if (!dataDpy->parent) {
  604         x = 0;
  605         y = 0;
  606     }
  607     /*  place it under its parent  */
  608     else {
  609         n = 0;
  610         XtSetArg(args[n], XtNheight, (XtArgVal) &height);       n++;
  611         XtGetValues(dataDpy->parent->popupshell, args, n);
  612         XtTranslateCoords(dataDpy->parent->popupshell, 30, (Position)height,
  613          &x, &y);
  614     }
  615     }
  616 
  617     /* Make sure the popup does not go outside of the screen */
  618     n = 0;
  619     XtSetArg(args[n], XtNwidth, (XtArgVal) &dataDpyWidth);              n++;
  620     XtSetArg(args[n], XtNheight, (XtArgVal) &dataDpyHeight);            n++;
  621     XtSetArg(args[n], XtNborderWidth, (XtArgVal) &dataDpyBorderWidth);  n++;
  622     XtGetValues(dataDpy->dataDpyWindow, args, n);
  623 
  624     n = 0;
  625     XtSetArg(args[n], XtNheight, (XtArgVal) &labelHeight);      n++;
  626     XtSetArg(args[n], XtNborderWidth, (XtArgVal) &labelBorderWidth);    n++;
  627     XtGetValues(dataDpy->label, args, n);
  628 
  629     popupHeight = dataDpyHeight + labelHeight + 2*labelBorderWidth +
  630           2*dataDpyBorderWidth;
  631     popupWidth = dataDpyWidth;
  632 
  633     screen = XtScreen(toplevel);
  634     screenHeight = XHeightOfScreen(screen);
  635     screenWidth = XWidthOfScreen(screen);
  636 
  637     if (x + popupWidth > screenWidth && y + popupHeight > screenHeight) {
  638     x = screenWidth - popupWidth;
  639     y = screenHeight - popupHeight;
  640     }
  641     else if (x + popupWidth > screenWidth)
  642     x = screenWidth - popupWidth;
  643     else if (y + popupHeight > screenHeight)
  644     y = screenHeight - popupHeight;
  645 
  646     n = 0;
  647     XtSetArg(args[n], XtNx, x);                     n++;
  648     XtSetArg(args[n], XtNy, y);                     n++;
  649     XtSetValues(dataDpy->popupshell, args, n);
  650 }
  651 
  652 /*
  653  *  Handler procedure called by parse().
  654  *  The main function to popup a data display.
  655  */
  656 void print_handler(output)
  657 char *output;
  658 {
  659     DataDpyRec  *dataDpy;
  660     int     i, j;
  661 
  662     if (!output) return;
  663     if (!PopupMode) return;
  664     PopupMode = False;
  665     XDefineCursor(display, XtWindow(toplevel), watch);
  666     if (Parent)
  667         XDefineCursor(display, XtWindow(Parent->dataDpyWindow), watch);
  668     UpdateMessageWindow("Click the label to pop down the data popup",NULL);
  669 
  670     /* Searches the table for an unused or empty slot */
  671     /* (PW)17OCT91 : test i < dataDpyTableSize first (else segment violation)*/
  672     for (i=0; dataDpyTable && i < dataDpyTableSize && dataDpyTable[i]
  673         && dataDpyTable[i]->state == USED ; i++);
  674     if (i == dataDpyTableSize) {            /* Table full */
  675     dataDpyTableSize += ADD_SIZE;
  676     dataDpyTable = (DataDpyRec **) XtRealloc ((void*)dataDpyTable, 
  677                dataDpyTableSize * sizeof(DataDpyRec *));
  678     for (j=i; j<dataDpyTableSize; j++)
  679         dataDpyTable[j] = NULL;
  680     }
  681 
  682     /*  Empty slot found, allocate a data structure and initializes some
  683     of the fields.  */
  684     if (dataDpyTable[i] == NULL) {
  685     dataDpyTable[i] = (DataDpyRec *) XtMalloc (sizeof(DataDpyRec));
  686     dataDpyTable[i]->state = EMPTY;
  687     dataDpyTable[i]->parent = NULL;
  688     dataDpyTable[i]->childlist = NULL;
  689     }
  690 
  691     dataDpy = dataDpyTable[i];
  692     dataDpy->id = i;                    /* not needed */
  693     dataDpy->buf = XtNewString(output);
  694     dataDpy->buflen = strlen(output);
  695     BuildLinePos(dataDpy);
  696 
  697     if (dataDpy->state == EMPTY)
  698     CreateDataPopup(dataDpy, Token.mesg);
  699     else if (dataDpy->state == UNUSED)
  700     UpdateDataPopup(dataDpy, Token.mesg);
  701 
  702     dataDpy->state = USED;              /* mark it used */
  703     if ((dataDpy->parent = Parent))
  704         AppendList(&Parent->childlist, dataDpy);
  705     else
  706         AppendList(&TopParentList, dataDpy);
  707 
  708     MovePopup(dataDpy);
  709     XtPopup(dataDpy->popupshell, XtGrabNone);
  710     if (dataDpy->parent)
  711         XUndefineCursor(display, XtWindow(dataDpy->parent->dataDpyWindow));
  712     XUndefineCursor(display, XtWindow(toplevel));
  713 }
  714 
  715 
  716 #ifdef GDB
  717 #define GOODCHARNAME(c)                         \
  718             (   (((c) >='a') &&  ((c) <= 'z'))  \
  719             ||  (((c) >='A') &&  ((c) <= 'Z'))  \
  720             ||  (((c) >='0') &&  ((c) <= '9'))  \
  721             ||  ((c) == '_')                    \
  722             ||  ((c) == '$')                    \
  723             )
  724 
  725 static char *result;        /* start of result buffer */
  726 static int result_index;    /* current index in result buffer */
  727 static char *start_txt;     /* pointer 1st char of output to parse */
  728 static char *curr_txt;      /* current pointer in output to parse */
  729 
  730 /*--------------------------------------------------------------------------+
  731 |                                                                           |
  732 |   Store a character into the buffer.                                      |
  733 |                                                                           |
  734 |   Note that characters are added to the buffer RIGHT TO LEFT !            |
  735 |   This is because we parse the output from right to left.                 |
  736 |                                                                           |
  737 |   If the result buffer is full, we set result to "".                      |
  738 |                                                                           |
  739 +--------------------------------------------------------------------------*/
  740 static void add_char(c)
  741 char c;
  742 {
  743     if (result_index == 0)  /* buffer full */
  744         {
  745         *result = 0;
  746         return;
  747         }
  748 
  749         if ((c == '.') && (result[result_index] == '.'))
  750                 return;         /* To prevent $1..name for pointers in 
  751                    g++ parents */
  752     
  753     result_index--;
  754     *(result+result_index) = c;
  755 }
  756 
  757 /*--------------------------------------------------------------------------+
  758 |                                                                           |
  759 |   Store a string into the buffer.                                         |
  760 |                                                                           |
  761 +--------------------------------------------------------------------------*/
  762 static void add_string(s)
  763 char *s;
  764 {
  765 int nbchar;
  766 
  767     nbchar = strlen(s);
  768     
  769     /* copy number from last digit */
  770     
  771     while (nbchar > 0)
  772         add_char(*(s + (--nbchar)));
  773 }
  774 
  775 /*--------------------------------------------------------------------------+
  776 |                                                                           |
  777 |   Store a number into the buffer.                                         |
  778 |                                                                           |
  779 +--------------------------------------------------------------------------*/
  780 static void add_num(number)
  781 int number;
  782 {
  783 char tmpnum[128];
  784 
  785     sprintf(tmpnum,"%d",number);
  786     add_string(tmpnum);
  787 }
  788 
  789 /*--------------------------------------------------------------------------+
  790 |                                                                           |
  791 |   Init buffer.                                                            |
  792 |                                                                           |
  793 |   Store a NULL character (as end of string).                              |
  794 |                                                                           |
  795 +--------------------------------------------------------------------------*/
  796 static void init_result(buffer,buflen)
  797 char *buffer;
  798 int buflen;
  799 {
  800     result = buffer;
  801     result_index = buflen;
  802     add_char(0);            /* end result by null char */
  803 }
  804 
  805 /*--------------------------------------------------------------------------+
  806 |                                                                           |
  807 |   Store the current variable or struct name.                              |
  808 |                                                                           |
  809 |   input :     curr_txt points to '=' character,                           |
  810 |               start_txt points to beginning of the parse string.          |
  811 |                                                                           |
  812 |   output :    curr_txt points to character before 1st character of        |
  813 |                   name.                                                   |
  814 |                                                                           |
  815 |   Note : we have to test for the beginning of the parse string,           |
  816 |   because add_name() is called also for adding the "$n" name              |
  817 |   of the gdb output.                                                      |
  818 |                                                                           |
  819 +--------------------------------------------------------------------------*/
  820 static void add_name ()
  821 {
  822     curr_txt--;                             /* point before '=' */
  823     while (*curr_txt == ' ') curr_txt--;    /* skip spaces */
  824     
  825     /* loop over name */
  826     while ((curr_txt >= start_txt) && GOODCHARNAME(*curr_txt))
  827         add_char(*curr_txt--);
  828 }
  829 
  830 /*--------------------------------------------------------------------------+
  831 |                                                                           |
  832 |   Skip all previous characters until corresponding " or ' character.      |
  833 |                                                                           |
  834 |   input : curr_txt points before ' or " character                         |
  835 |                                                                           |
  836 |   output : curr_txt points before corresponding ' or " character.         |
  837 |                                                                           |
  838 +--------------------------------------------------------------------------*/
  839 void search_char(c)
  840 char c;
  841 {
  842     while(1)
  843         {
  844         while(c != *(curr_txt--));
  845         
  846         /* make sure there is not a '\' just before */
  847         
  848         if (*curr_txt != '\\')
  849             return;
  850         }
  851 }
  852 
  853 /*--------------------------------------------------------------------------+
  854 |                                                                           |
  855 |   Skip all previous characters until previous corresponding '{'.          |
  856 |   All "{...}" sequences are skip.                                         |
  857 |   Return the array item number (if applicable)                            |
  858 |                                                                           |
  859 |   input :     curr_txt points to string.                                  |
  860 |                                                                           |
  861 |   output :    curr_txt points to character before '{'                     |
  862 |               return number of commas                                     |
  863 |                                                                           |
  864 +--------------------------------------------------------------------------*/
  865 static int skip_level()
  866 {
  867 int nbcommas;
  868 char c;
  869 
  870     nbcommas = 0;
  871     
  872     while(1)
  873         {
  874         switch (c = *(curr_txt--))
  875             {
  876             case '{' :
  877                 return nbcommas;
  878             
  879             case ',' :
  880                 nbcommas++;
  881                 break;
  882                 
  883             case '}' :
  884                 skip_level();
  885                 break;
  886             
  887             case '"' :
  888             case '\'' :
  889                 search_char(c);
  890                 break;
  891                 
  892             default:
  893                 break;
  894             }
  895         }
  896 }
  897 
  898 /*--------------------------------------------------------------------------+
  899 |                                                                           |
  900 |   Function to parse an output of a gdb print from                         |
  901 |   a pointer (0x...) and return a command line to                          |
  902 |   print *(0x...)                                                          |
  903 |                                                                           |
  904 |   input : command line pointer (LINESIZ size),                            |
  905 |           pointer print output,                                           |
  906 |           pointer 0x...                                                   |
  907 |                                                                           |
  908 |   output : command line (stored RIGHT justified in commandline)           |
  909 |                                                                           |
  910 |   example                                                                 |
  911 |                                                                           |
  912 |       start = "$1 = { (struct foo *) 0x1224}"                             |
  913 |       current points to 0x1224 in start,                                  |
  914 |                                                                           |
  915 |       commandline = "print *($1)"                                         |
  916 |                                                                           |
  917 +--------------------------------------------------------------------------*/
  918 char *parse_gdb_print (commandline, start, current)
  919 char *commandline;
  920 char *start;
  921 char *current;
  922 {
  923 char *begin;
  924 
  925     start_txt = start;      /* in static variables */
  926     curr_txt = current;
  927 
  928     begin = strchr(start,'=');  /* find '=' in "$n =" */
  929     
  930     if (!begin)
  931         return NULL;
  932         
  933     init_result(commandline,LINESIZ);
  934 
  935     add_string(")\n");
  936     
  937     while (begin <= curr_txt)
  938         {
  939         switch (*curr_txt)
  940             {
  941             case '=':
  942                 add_name();
  943                 
  944                 /* stop now if we just parsed the '=' in "$n =" */
  945                 if (curr_txt >= start_txt)
  946                     {
  947                     add_char('.');
  948                     skip_level();
  949                     }
  950                 break;
  951             
  952             case ',':
  953             case '{':
  954                 add_char(']');
  955                 add_num(skip_level());
  956                 add_char('[');
  957                 break;
  958         
  959             default:
  960                 curr_txt--;
  961             }
  962         }
  963         
  964     add_string("print *(");
  965     
  966     if (debug)
  967         fprintf(stderr,"datadpy=%s\n",result+result_index);
  968     
  969     return result+result_index;
  970 }
  971 
  972 #endif /* GDB */