1 /* Code for handling XREF output from GNU C++.
2 Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@cygnus.com)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
30 extern char *getpwd
PROTO((void));
32 /* The character(s) used to join a directory specification (obtained with
33 getwd or equivalent) with a non-absolute file name. */
35 #ifndef FILE_NAME_JOINER
36 #define FILE_NAME_JOINER "/"
39 /* Nonzero if NAME as a file name is absolute. */
40 #ifndef FILE_NAME_ABSOLUTE_P
41 #define FILE_NAME_ABSOLUTE_P(NAME) (NAME[0] == '/')
44 /* For cross referencing. */
48 /************************************************************************/
50 /* Common definitions */
52 /************************************************************************/
61 #define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
64 /* Return a malloc'd copy of STR. */
66 ((char *) ((str) == NULL ? NULL \
67 : (char *) strcpy ((char *) malloc (strlen ((str)) + 1), (str))))
68 #define SFREE(str) (str != NULL && (free(str),0))
70 #define STREQL(s1,s2) (strcmp((s1),(s2)) == 0)
71 #define STRNEQ(s1,s2) (strcmp((s1),(s2)) != 0)
72 #define STRLSS(s1,s2) (strcmp((s1),(s2)) < 0)
73 #define STRLEQ(s1,s2) (strcmp((s1),(s2)) <= 0)
74 #define STRGTR(s1,s2) (strcmp((s1),(s2)) > 0)
75 #define STRGEQ(s1,s2) (strcmp((s1),(s2)) >= 0)
77 /************************************************************************/
79 /* Type definitions */
81 /************************************************************************/
84 typedef struct _XREF_FILE
* XREF_FILE
;
85 typedef struct _XREF_SCOPE
* XREF_SCOPE
;
87 typedef struct _XREF_FILE
94 typedef struct _XREF_SCOPE
103 /************************************************************************/
107 /************************************************************************/
109 static char doing_xref
= 0;
110 static FILE * xref_file
= NULL
;
111 static char xref_name
[1024];
112 static XREF_FILE all_files
= NULL
;
113 static char * wd_name
= NULL
;
114 static XREF_SCOPE cur_scope
= NULL
;
115 static int scope_ctr
= 0;
116 static XREF_FILE last_file
= NULL
;
117 static tree last_fndecl
= NULL
;
119 /************************************************************************/
121 /* Forward definitions */
123 /************************************************************************/
124 static void gen_assign
PROTO((XREF_FILE
, tree
));
125 static XREF_FILE find_file
PROTO((char *));
126 static char * filename
PROTO((XREF_FILE
));
127 static char * fctname
PROTO((tree
));
128 static char * declname
PROTO((tree
));
129 static void simplify_type
PROTO((char *));
130 static char * fixname
PROTO((char *, char *));
131 static void open_xref_file
PROTO((char *));
133 /* Start cross referencing. FILE is the name of the file we xref. */
136 GNU_xref_begin (file
)
141 if (file
!= NULL
&& STRNEQ (file
,"-"))
143 open_xref_file(file
);
148 /* Finish cross-referencing. ERRCNT is the number of errors
157 if (!doing_xref
) return;
159 xf
= find_file (input_filename
);
160 if (xf
== NULL
) return;
162 while (cur_scope
!= NULL
)
163 GNU_xref_end_scope(cur_scope
->gid
,0,0,0);
167 if (xref_file
== NULL
) return;
174 if (ect
> 0) unlink (xref_name
);
177 /* Write out xref for file named NAME. */
185 if (!doing_xref
|| name
== NULL
) return;
187 if (xref_file
== NULL
)
189 open_xref_file (name
);
190 if (!doing_xref
) return;
193 if (all_files
== NULL
)
194 fprintf(xref_file
,"SCP * 0 0 0 0 RESET\n");
196 xf
= find_file (name
);
197 if (xf
!= NULL
) return;
199 xf
= PALLOC (XREF_FILE_INFO
);
200 xf
->name
= SALLOC (name
);
201 xf
->next
= all_files
;
207 if (FILE_NAME_ABSOLUTE_P (name
) || ! wd_name
)
208 xf
->outname
= xf
->name
;
212 = (char *) malloc (strlen (wd_name
) + strlen (FILE_NAME_JOINER
)
213 + strlen (name
) + 1);
214 sprintf (nmbuf
, "%s%s%s", wd_name
, FILE_NAME_JOINER
, name
);
219 fprintf (xref_file
, "FIL %s %s 0\n", name
, wd_name
);
225 /* Start a scope identified at level ID. */
228 GNU_xref_start_scope (id
)
234 if (!doing_xref
) return;
235 xf
= find_file (input_filename
);
237 xs
= PALLOC (XREF_SCOPE_INFO
);
240 if (xs
->start
<= 0) xs
->start
= 1;
242 xs
->lid
= ++scope_ctr
;
243 xs
->outer
= cur_scope
;
247 /* Finish a scope at level ID.
250 KEEP is nonzero iff this scope is retained (nonzero if it's
251 a compiler-generated invisible scope).
255 GNU_xref_end_scope (id
,inid
,prm
,keep
)
261 XREF_SCOPE xs
,lxs
,oxs
;
264 if (!doing_xref
) return;
265 xf
= find_file (input_filename
);
266 if (xf
== NULL
) return;
269 for (xs
= cur_scope
; xs
!= NULL
; xs
= xs
->outer
)
271 if (xs
->gid
== id
) break;
274 if (xs
== NULL
) return;
277 for (oxs
= cur_scope
; oxs
!= NULL
; oxs
= oxs
->outer
) {
278 if (oxs
->gid
== inid
) break;
280 if (oxs
== NULL
) return;
284 if (prm
== 2) stype
= "SUE";
285 else if (prm
!= 0) stype
= "ARGS";
286 else if (keep
== 2 || inid
!= 0) stype
= "INTERN";
287 else stype
= "EXTERN";
289 fprintf (xref_file
, "SCP %s %d %d %d ",
290 filename (xf
), xs
->start
, lineno
,xs
->lid
);
291 fprintf (xref_file
, HOST_WIDE_INT_PRINT_DEC
, inid
);
292 fprintf (xref_file
, " %s\n", stype
);
294 if (lxs
== NULL
) cur_scope
= xs
->outer
;
295 else lxs
->outer
= xs
->outer
;
300 /* Output a reference to NAME in FNDECL. */
303 GNU_xref_ref (fndecl
,name
)
309 if (!doing_xref
) return;
310 xf
= find_file (input_filename
);
311 if (xf
== NULL
) return;
313 fprintf (xref_file
, "REF %s %d %s %s\n",
314 filename (xf
), lineno
, fctname (fndecl
), name
);
317 /* Output a reference to DECL in FNDECL. */
320 GNU_xref_decl (fndecl
,decl
)
330 if (!doing_xref
) return;
331 xf
= find_file (input_filename
);
332 if (xf
== NULL
) return;
336 if (TREE_CODE (decl
) == TYPE_DECL
) cls
= "TYPEDEF";
337 else if (TREE_CODE (decl
) == FIELD_DECL
) cls
= "FIELD";
338 else if (TREE_CODE (decl
) == VAR_DECL
)
340 if (fndecl
== NULL
&& TREE_STATIC(decl
)
341 && TREE_READONLY(decl
) && DECL_INITIAL(decl
) != 0
342 && !TREE_PUBLIC(decl
) && !DECL_EXTERNAL(decl
)
343 && DECL_MODE(decl
) != BLKmode
) cls
= "CONST";
344 else if (DECL_EXTERNAL(decl
)) cls
= "EXTERN";
345 else if (TREE_PUBLIC(decl
)) cls
= "EXTDEF";
346 else if (TREE_STATIC(decl
)) cls
= "STATIC";
347 else if (DECL_REGISTER(decl
)) cls
= "REGISTER";
350 else if (TREE_CODE (decl
) == PARM_DECL
) cls
= "PARAM";
351 else if (TREE_CODE (decl
) == FIELD_DECL
) cls
= "FIELD";
352 else if (TREE_CODE (decl
) == CONST_DECL
) cls
= "CONST";
353 else if (TREE_CODE (decl
) == FUNCTION_DECL
)
355 if (DECL_EXTERNAL (decl
)) cls
= "EXTERN";
356 else if (TREE_PUBLIC (decl
)) cls
= "EFUNCTION";
357 else cls
= "SFUNCTION";
359 else if (TREE_CODE (decl
) == LABEL_DECL
) cls
= "LABEL";
360 else if (TREE_CODE (decl
) == UNION_TYPE
)
363 decl
= TYPE_NAME (decl
);
366 else if (TREE_CODE (decl
) == RECORD_TYPE
)
368 if (CLASSTYPE_DECLARED_CLASS (decl
)) cls
= "CLASSID";
369 else if (IS_SIGNATURE (decl
)) cls
= "SIGNATUREID";
370 else cls
= "STRUCTID";
371 decl
= TYPE_NAME (decl
);
374 else if (TREE_CODE (decl
) == ENUMERAL_TYPE
)
377 decl
= TYPE_NAME (decl
);
380 else if (TREE_CODE (decl
) == TEMPLATE_DECL
)
382 if (TREE_CODE (DECL_RESULT (decl
)) == TYPE_DECL
)
384 else if (TREE_CODE (DECL_RESULT (decl
)) == FUNCTION_DECL
)
386 else if (TREE_CODE (DECL_RESULT (decl
)) == VAR_DECL
)
389 my_friendly_abort (358);
392 else cls
= "UNKNOWN";
394 if (decl
== NULL
|| DECL_NAME (decl
) == NULL
) return;
396 if (uselin
&& decl
->decl
.linenum
> 0 && decl
->decl
.filename
!= NULL
)
398 xf1
= find_file (decl
->decl
.filename
);
401 lineno
= decl
->decl
.linenum
;
406 if (DECL_ASSEMBLER_NAME (decl
))
407 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
409 name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
411 strcpy (buf
, type_as_string (TREE_TYPE (decl
), 0));
414 fprintf (xref_file
, "DCL %s %d %s %d %s %s %s\n",
415 filename(xf
), lineno
, name
,
416 (cur_scope
!= NULL
? cur_scope
->lid
: 0),
417 cls
, fctname(fndecl
), buf
);
419 if (STREQL (cls
, "STRUCTID") || STREQL (cls
, "UNIONID")
420 || STREQL (cls
, "SIGNATUREID"))
423 fprintf (xref_file
, "DCL %s %d %s %d %s %s %s\n",
424 filename(xf
), lineno
,name
,
425 (cur_scope
!= NULL
? cur_scope
->lid
: 0),
426 cls
, fctname(fndecl
), buf
);
430 /* Output a reference to a call to NAME in FNDECL. */
433 GNU_xref_call (fndecl
, name
)
441 if (!doing_xref
) return;
442 xf
= find_file (input_filename
);
443 if (xf
== NULL
) return;
444 name
= fixname (name
, buf
);
446 for (s
= name
; *s
!= 0; ++s
)
447 if (*s
== '_' && s
[1] == '_') break;
448 if (*s
!= 0) GNU_xref_ref (fndecl
, name
);
450 fprintf (xref_file
, "CAL %s %d %s %s\n",
451 filename (xf
), lineno
, name
, fctname (fndecl
));
454 /* Output cross-reference info about FNDECL. If non-NULL,
455 ARGS are the arguments for the function (i.e., before the FUNCTION_DECL
456 has been fully built). */
459 GNU_xref_function (fndecl
, args
)
467 if (!doing_xref
) return;
468 xf
= find_file (input_filename
);
469 if (xf
== NULL
) return;
473 if (args
== NULL
) args
= DECL_ARGUMENTS (fndecl
);
475 GNU_xref_decl (NULL
, fndecl
);
477 for ( ; args
!= NULL
; args
= TREE_CHAIN (args
))
479 GNU_xref_decl (fndecl
,args
);
480 if (ct
!= 0) strcat (buf
,",");
481 strcat (buf
, declname (args
));
485 fprintf (xref_file
, "PRC %s %d %s %d %d %s\n",
486 filename(xf
), lineno
, declname(fndecl
),
487 (cur_scope
!= NULL
? cur_scope
->lid
: 0),
491 /* Output cross-reference info about an assignment to NAME. */
494 GNU_xref_assign(name
)
499 if (!doing_xref
) return;
500 xf
= find_file(input_filename
);
501 if (xf
== NULL
) return;
503 gen_assign(xf
, name
);
515 switch (TREE_CODE (name
))
517 case IDENTIFIER_NODE
:
518 s
= IDENTIFIER_POINTER(name
);
524 gen_assign(xf
, TREE_OPERAND(name
, 0));
525 gen_assign(xf
, TREE_OPERAND(name
, 1));
531 gen_assign(xf
, TREE_OPERAND(name
, 0));
534 gen_assign(xf
, TREE_OPERAND(name
, 1));
541 fprintf(xref_file
, "ASG %s %d %s\n", filename(xf
), lineno
, s
);
548 if (cls
&& TREE_CODE_CLASS (TREE_CODE (cls
)) == 't')
549 cls
= TYPE_NAME (cls
);
550 if (cls
&& TREE_CODE_CLASS (TREE_CODE (cls
)) == 'd')
551 cls
= DECL_NAME (cls
);
552 if (cls
&& TREE_CODE (cls
) == IDENTIFIER_NODE
)
553 return IDENTIFIER_POINTER (cls
);
557 /* Output cross-reference info about a class hierarchy.
558 CLS is the class type of interest. BASE is a baseclass
559 for CLS. PUB and VIRT give the access info about
560 the class derivation. FRND is nonzero iff BASE is a friend
563 ??? Needs to handle nested classes. */
566 GNU_xref_hier(cls
, base
, pub
, virt
, frnd
)
575 if (!doing_xref
) return;
576 xf
= find_file(input_filename
);
577 if (xf
== NULL
) return;
579 fprintf(xref_file
, "HIE %s %d %s %s %d %d %d\n",
580 filename(xf
), lineno
, classname (cls
), classname (base
),
584 /* Output cross-reference info about class members. CLS
585 is the containing type; FLD is the class member. */
588 GNU_xref_member(cls
, fld
)
596 #ifdef XREF_SHORT_MEMBER_NAMES
599 char buf
[1024], bufa
[1024];
601 if (!doing_xref
) return;
602 xf
= find_file(fld
->decl
.filename
);
603 if (xf
== NULL
) return;
605 if (TREE_PRIVATE (fld
)) prot
= "PRIVATE";
606 else if (TREE_PROTECTED(fld
)) prot
= "PROTECTED";
607 else prot
= "PUBLIC";
610 if (TREE_CODE (fld
) == FUNCTION_DECL
&& DECL_CONST_MEMFUNC_P(fld
))
612 else if (TREE_CODE (fld
) == CONST_DECL
)
616 if (TREE_CODE (fld
) == FUNCTION_DECL
&& DECL_ABSTRACT_VIRTUAL_P(fld
))
619 d
= IDENTIFIER_POINTER(cls
);
620 sprintf(buf
, "%d%s", (int) strlen(d
), d
);
621 #ifdef XREF_SHORT_MEMBER_NAMES
624 strcpy(bufa
, declname(fld
));
626 #ifdef XREF_SHORT_MEMBER_NAMES
627 for (p
= &bufa
[1]; *p
!= 0; ++p
)
629 if (p
[0] == '_' && p
[1] == '_' && p
[2] >= '0' && p
[2] <= '9') {
630 if (strncmp(&p
[2], buf
, i
) == 0) *p
= 0;
633 else if (p
[0] == '_' && p
[1] == '_' && p
[2] == 'C' && p
[3] >= '0' && p
[3] <= '9') {
634 if (strncmp(&p
[3], buf
, i
) == 0) *p
= 0;
640 fprintf(xref_file
, "MEM %s %d %s %s %s %d %d %d %d %d %d %d\n",
641 filename(xf
), fld
->decl
.linenum
, d
, bufa
, prot
,
642 (TREE_CODE (fld
) == FUNCTION_DECL
? 0 : 1),
643 (DECL_INLINE (fld
) ? 1 : 0),
644 (DECL_LANG_SPECIFIC(fld
) && DECL_FRIEND_P(fld
) ? 1 : 0),
645 (DECL_VINDEX(fld
) ? 1 : 0),
646 (TREE_STATIC(fld
) ? 1 : 0),
650 /* Find file entry given name. */
658 for (xf
= all_files
; xf
!= NULL
; xf
= xf
->next
) {
659 if (STREQL(name
, xf
->name
)) break;
665 /* Return filename for output purposes. */
676 if (last_file
== xf
) return "*";
683 /* Return function name for output purposes. */
689 static char fctbuf
[1024];
692 if (fndecl
== NULL
&& last_fndecl
== NULL
) return "*";
700 if (fndecl
== last_fndecl
) return "*";
702 last_fndecl
= fndecl
;
704 s
= declname(fndecl
);
705 s
= fixname(s
, fctbuf
);
710 /* Return decl name for output purposes. */
716 if (DECL_NAME (dcl
) == NULL
) return "?";
718 if (DECL_ASSEMBLER_NAME (dcl
))
719 return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (dcl
));
721 return IDENTIFIER_POINTER (DECL_NAME (dcl
));
724 /* Simplify a type string by removing unneeded parenthesis. */
734 while (i
> 0 && ISSPACE((unsigned char) typ
[i
-1])) typ
[--i
] = 0;
736 if (i
> 7 && STREQL(&typ
[i
-5], "const"))
742 if (typ
[i
-1] != ')') return;
747 if (*s
== ')') ++lvl
;
761 if (*s
!= 0 && s
[-1] == ')')
765 if (*s
== '(') s
[2] = 0;
766 else if (*s
== ':') {
767 while (*s
!= '(') --s
;
774 /* Fixup a function name (take care of embedded spaces). */
800 if (fg
== 0) return nam
;
805 /* Open file for xreffing. */
813 #ifdef XREF_FILE_NAME
814 XREF_FILE_NAME (xref_name
, file
);
816 s
= rindex (file
, '/');
818 sprintf (xref_name
, ".%s.gxref", file
);
822 strcpy (xref_name
, file
);
823 t
= rindex (xref_name
, '/');
827 strcat (t
, ".gxref");
829 #endif /* no XREF_FILE_NAME */
831 xref_file
= fopen(xref_name
, "w");
833 if (xref_file
== NULL
)
835 error("Can't create cross-reference file `%s'", xref_name
);