"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