home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gcc-2.3.3-src.lha / gcc-2.3.3 / cp-xref.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-07  |  17.3 KB  |  831 lines

  1. /* Code for handling XREF output from GNU C++.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@cygnus.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  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)
  10. any later version.
  11.  
  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.
  16.  
  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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. #include "config.h"
  23. #include "tree.h"
  24. #include <stdio.h>
  25. #include "cp-tree.h"
  26. #include "input.h"
  27.  
  28. #include <ctype.h>
  29.  
  30. char *getpwd ();
  31.  
  32. extern char *index ();
  33. extern char *rindex ();
  34.  
  35. /* The character(s) used to join a directory specification (obtained with
  36.    getwd or equivalent) with a non-absolute file name.  */
  37.  
  38. #ifndef FILE_NAME_JOINER
  39. #define FILE_NAME_JOINER "/"
  40. #endif
  41.  
  42. /* Nonzero if NAME as a file name is absolute.  */
  43. #ifndef FILE_NAME_ABSOLUTE_P
  44. #define FILE_NAME_ABSOLUTE_P(NAME) (NAME[0] == '/')
  45. #endif
  46.  
  47. /* For cross referencing.  */
  48.  
  49. int flag_gnu_xref;
  50.  
  51. /************************************************************************/
  52. /*                                    */
  53. /*    Common definitions                        */
  54. /*                                    */
  55. /************************************************************************/
  56.  
  57. typedef int    Integer;
  58. typedef char *    String;
  59.  
  60.  
  61. #ifndef TRUE
  62. #define TRUE 1
  63. #endif
  64. #ifndef FALSE
  65. #define FALSE 0
  66. #endif
  67. #ifndef NULL
  68. #define NULL 0
  69. #endif
  70.  
  71. #define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
  72.  
  73.  
  74. /* Return a malloc'd copy of STR.  */
  75. #define SALLOC(str) \
  76.  ((String) ((str) == NULL ? NULL    \
  77.         : strcpy ((String) malloc (strlen ((str)) + 1), (str))))
  78. #define SFREE(str) (str != NULL && (free(str),0))
  79.  
  80. #define STREQL(s1,s2) (strcmp((s1),(s2)) == 0)
  81. #define STRNEQ(s1,s2) (strcmp((s1),(s2)) != 0)
  82. #define STRLSS(s1,s2) (strcmp((s1),(s2)) < 0)
  83. #define STRLEQ(s1,s2) (strcmp((s1),(s2)) <= 0)
  84. #define STRGTR(s1,s2) (strcmp((s1),(s2)) > 0)
  85. #define STRGEQ(s1,s2) (strcmp((s1),(s2)) >= 0)
  86.  
  87. /************************************************************************/
  88. /*                                    */
  89. /*    Type definitions                        */
  90. /*                                    */
  91. /************************************************************************/
  92.  
  93.  
  94. typedef struct _XREF_FILE *    XREF_FILE;
  95. typedef struct _XREF_SCOPE *    XREF_SCOPE;
  96.  
  97. typedef struct _XREF_FILE
  98. {
  99.   String name;
  100.   String outname;
  101.   XREF_FILE next;
  102. } XREF_FILE_INFO;
  103.  
  104. typedef struct _XREF_SCOPE
  105. {
  106.   Integer gid;
  107.   Integer lid;
  108.   XREF_FILE file;
  109.   Integer start;
  110.   XREF_SCOPE outer;
  111. } XREF_SCOPE_INFO;
  112.  
  113. /************************************************************************/
  114. /*                                    */
  115. /*    Local storage                            */
  116. /*                                    */
  117. /************************************************************************/
  118.  
  119. static    char        doing_xref = 0;
  120. static    FILE *        xref_file = NULL;
  121. static    char        xref_name[1024];
  122. static    XREF_FILE    all_files = NULL;
  123. static    String        wd_name = NULL;
  124. static    XREF_SCOPE    cur_scope = NULL;
  125. static    Integer     scope_ctr = 0;
  126. static    XREF_FILE    last_file = NULL;
  127. static    tree        last_fndecl = NULL;
  128.  
  129. /************************************************************************/
  130. /*                                    */
  131. /*    Forward definitions                        */
  132. /*                                    */
  133. /************************************************************************/
  134.  
  135. extern    void        GNU_xref_begin();
  136. extern    void        GNU_xref_end();
  137. extern    void        GNU_xref_file();
  138. extern    void        GNU_xref_start_scope();
  139. extern    void        GNU_xref_end_scope();
  140. extern    void        GNU_xref_ref();
  141. extern    void        GNU_xref_decl();
  142. extern    void        GNU_xref_call();
  143. extern    void        GNU_xref_function();
  144. extern    void        GNU_xref_assign();
  145. extern    void        GNU_xref_hier();
  146. extern    void        GNU_xref_member();
  147.  
  148. static    void        gen_assign();
  149. static    XREF_FILE    find_file();
  150. static    String        filename();
  151. static    String        fctname();
  152. static    String        declname();
  153. static    void        simplify_type();
  154. static    String        fixname();
  155. static    void        open_xref_file();
  156.  
  157. extern    char *        type_as_string();
  158.  
  159. /* Start cross referencing.  FILE is the name of the file we xref.  */
  160.  
  161. void
  162. GNU_xref_begin (file)
  163.    String file;
  164. {
  165.   doing_xref = 1;
  166.  
  167.   if (file != NULL && STRNEQ (file,"-"))
  168.     {
  169.       open_xref_file(file);
  170.       GNU_xref_file(file);
  171.     }
  172. }
  173.  
  174. /* Finish cross-referencing.  ERRCNT is the number of errors
  175.    we encountered.  */
  176.  
  177. void
  178. GNU_xref_end (ect)
  179.    int ect;
  180. {
  181.   XREF_FILE xf;
  182.  
  183.   if (!doing_xref) return;
  184.  
  185.   xf = find_file (input_filename);
  186.   if (xf == NULL) return;
  187.  
  188.   while (cur_scope != NULL)
  189.     GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
  190.  
  191.   doing_xref = 0;
  192.  
  193.   if (xref_file == NULL) return;
  194.  
  195.   fclose (xref_file);
  196.  
  197.   xref_file = NULL;
  198.   all_files = NULL;
  199.  
  200.   if (ect > 0) unlink (xref_name);
  201. }
  202.  
  203. /* Write out xref for file named NAME.  */
  204.  
  205. void
  206. GNU_xref_file (name)
  207.    String name;
  208. {
  209.   XREF_FILE xf;
  210.  
  211.   if (!doing_xref || name == NULL) return;
  212.  
  213.   if (xref_file == NULL)
  214.     {
  215.       open_xref_file (name);
  216.       if (!doing_xref) return;
  217.     }
  218.  
  219.   if (all_files == NULL)
  220.     fprintf(xref_file,"SCP * 0 0 0 0 RESET\n");
  221.  
  222.   xf = find_file (name);
  223.   if (xf != NULL) return;
  224.  
  225.   xf = PALLOC (XREF_FILE_INFO);
  226.   xf->name = SALLOC (name);
  227.   xf->next = all_files;
  228.   all_files = xf;
  229.  
  230.   if (wd_name == NULL)
  231.     wd_name = getpwd ();
  232.  
  233.   if (FILE_NAME_ABSOLUTE_P (name) || ! wd_name)
  234.     xf->outname = xf->name;
  235.   else
  236.     {
  237.       char *nmbuf
  238.     = (char *) malloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
  239.                + strlen (name) + 1);
  240.       sprintf (nmbuf, "%s%s%s", wd_name, FILE_NAME_JOINER, name);
  241.       name = nmbuf;
  242.       xf->outname = nmbuf;
  243.     }
  244.  
  245.   fprintf (xref_file, "FIL %s %s 0\n", name, wd_name);
  246.  
  247.   filename (xf);
  248.   fctname (NULL);
  249. }
  250.  
  251. /* Start a scope identified at level ID.  */
  252.  
  253. void
  254. GNU_xref_start_scope (id)
  255.    Integer id;
  256. {
  257.   XREF_SCOPE xs;
  258.   XREF_FILE xf;
  259.  
  260.   if (!doing_xref) return;
  261.   xf = find_file (input_filename);
  262.  
  263.   xs = PALLOC (XREF_SCOPE_INFO);
  264.   xs->file = xf;
  265.   xs->start = lineno;
  266.   if (xs->start <= 0) xs->start = 1;
  267.   xs->gid = id;
  268.   xs->lid = ++scope_ctr;
  269.   xs->outer = cur_scope;
  270.   cur_scope = xs;
  271. }
  272.  
  273. /* Finish a scope at level ID.
  274.    INID is ???
  275.    PRM is ???
  276.    KEEP is nonzero iff this scope is retained (nonzero if it's
  277.    a compiler-generated invisible scope).
  278.    TRNS is ???  */
  279.  
  280. void
  281. GNU_xref_end_scope (id,inid,prm,keep,trns)
  282.    Integer id;
  283.    Integer inid;
  284.    Integer prm,keep,trns;
  285. {
  286.   XREF_FILE xf;
  287.   XREF_SCOPE xs,lxs,oxs;
  288.   String stype;
  289.  
  290.   if (!doing_xref) return;
  291.   xf = find_file (input_filename);
  292.   if (xf == NULL) return;
  293.  
  294.   lxs = NULL;
  295.   for (xs = cur_scope; xs != NULL; xs = xs->outer)
  296.     {
  297.       if (xs->gid == id) break;
  298.       lxs = xs;
  299.     }
  300.   if (xs == NULL) return;
  301.  
  302.   if (inid != 0) {
  303.     for (oxs = cur_scope; oxs != NULL; oxs = oxs->outer) {
  304.       if (oxs->gid == inid) break;
  305.     }
  306.     if (oxs == NULL) return;
  307.     inid = oxs->lid;
  308.   }
  309.  
  310.   if (prm == 2) stype = "SUE";
  311.   else if (prm != 0) stype = "ARGS";
  312.   else if (keep == 2 || inid != 0) stype = "INTERN";
  313.   else stype = "EXTERN";
  314.  
  315.   fprintf (xref_file,"SCP %s %d %d %d %d %s\n",
  316.        filename (xf), xs->start, lineno,xs->lid, inid, stype);
  317.  
  318.   if (lxs == NULL) cur_scope = xs->outer;
  319.   else lxs->outer = xs->outer;
  320.  
  321.   free (xs);
  322. }
  323.  
  324. /* Output a reference to NAME in FNDECL.  */
  325.  
  326. void
  327. GNU_xref_ref (fndecl,name)
  328.    tree fndecl;
  329.    String name;
  330. {
  331.   XREF_FILE xf;
  332.  
  333.   if (!doing_xref) return;
  334.   xf = find_file (input_filename);
  335.   if (xf == NULL) return;
  336.  
  337.   fprintf (xref_file, "REF %s %d %s %s\n",
  338.        filename (xf), lineno, fctname (fndecl), name);
  339. }
  340.  
  341. /* Output a reference to DECL in FNDECL.  */
  342.  
  343. void
  344. GNU_xref_decl (fndecl,decl)
  345.    tree fndecl;
  346.    tree decl;
  347. {
  348.   XREF_FILE xf,xf1;
  349.   String cls;
  350.   String name;
  351.   char buf[10240];
  352.   Integer uselin;
  353.  
  354.   if (!doing_xref) return;
  355.   xf = find_file (input_filename);
  356.   if (xf == NULL) return;
  357.  
  358.   uselin = FALSE;
  359.  
  360.   if (TREE_CODE (decl) == TYPE_DECL) cls = "TYPEDEF";
  361.   else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
  362.   else if (TREE_CODE (decl) == VAR_DECL)
  363.     {
  364.       if (fndecl == NULL && TREE_STATIC(decl)
  365.       && TREE_READONLY(decl) && DECL_INITIAL(decl) != 0
  366.       && !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl)
  367.       && DECL_MODE(decl) != BLKmode) cls = "CONST";
  368.       else if (DECL_EXTERNAL(decl)) cls = "EXTERN";
  369.       else if (TREE_PUBLIC(decl)) cls = "EXTDEF";
  370.       else if (TREE_STATIC(decl)) cls = "STATIC";
  371.       else if (DECL_REGISTER(decl)) cls = "REGISTER";
  372.       else cls = "AUTO";
  373.     }
  374.   else if (TREE_CODE (decl) == PARM_DECL) cls = "PARAM";
  375.   else if (TREE_CODE (decl) == FIELD_DECL) cls = "FIELD";
  376.   else if (TREE_CODE (decl) == CONST_DECL) cls = "CONST";
  377.   else if (TREE_CODE (decl) == FUNCTION_DECL)
  378.     {
  379.       if (DECL_EXTERNAL (decl)) cls = "EXTERN";
  380.       else if (TREE_PUBLIC (decl)) cls = "EFUNCTION";
  381.       else cls = "SFUNCTION";
  382.     }
  383.   else if (TREE_CODE (decl) == LABEL_DECL) cls = "LABEL";
  384.   else if (TREE_CODE (decl) == UNION_TYPE)
  385.     {
  386.       cls = "UNIONID";
  387.       decl = TYPE_NAME (decl);
  388.       uselin = TRUE;
  389.     }
  390.   else if (TREE_CODE (decl) == RECORD_TYPE)
  391.     {
  392.       if (CLASSTYPE_DECLARED_CLASS (decl)) cls = "CLASSID";
  393.       else cls = "STRUCTID";
  394.       decl = TYPE_NAME (decl);
  395.       uselin = TRUE;
  396.     }
  397.   else if (TREE_CODE (decl) == ENUMERAL_TYPE)
  398.     {
  399.       cls = "ENUMID";
  400.       decl = TYPE_NAME (decl);
  401.       uselin = TRUE;
  402.     }
  403.   else cls = "UNKNOWN";
  404.  
  405.   if (decl == NULL || DECL_NAME (decl) == NULL) return;
  406.  
  407.   if (uselin && decl->decl.linenum > 0 && decl->decl.filename != NULL)
  408.     {
  409.       xf1 = find_file (decl->decl.filename);
  410.       if (xf1 != NULL)
  411.     {
  412.       lineno = decl->decl.linenum;
  413.       xf = xf1;
  414.     }
  415.     }
  416.  
  417.   if (DECL_ASSEMBLER_NAME (decl))
  418.     name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
  419.   else
  420.     name = IDENTIFIER_POINTER (DECL_NAME (decl));
  421.  
  422.   strcpy (buf, type_as_string (TREE_TYPE (decl)));
  423.   simplify_type (buf);
  424.  
  425.   fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
  426.        filename(xf), lineno, name,
  427.        (cur_scope != NULL ? cur_scope->lid : 0),
  428.        cls, fctname(fndecl), buf);
  429.  
  430.   if (STREQL (cls, "STRUCTID") || STREQL (cls, "UNIONID"))
  431.     {
  432.       cls = "CLASSID";
  433.       fprintf (xref_file, "DCL %s %d %s %d %s %s %s\n",
  434.            filename(xf), lineno,name,
  435.            (cur_scope != NULL ? cur_scope->lid : 0),
  436.            cls, fctname(fndecl), buf);
  437.     }
  438. }
  439.  
  440. /* Output a reference to a call to NAME in FNDECL.  */
  441.  
  442. void
  443. GNU_xref_call (fndecl, name)
  444.    tree fndecl;
  445.    String name;
  446. {
  447.   XREF_FILE xf;
  448.   char buf[1024];
  449.   String s;
  450.  
  451.   if (!doing_xref) return;
  452.   xf = find_file (input_filename);
  453.   if (xf == NULL) return;
  454.   name = fixname (name, buf);
  455.  
  456.   for (s = name; *s != 0; ++s)
  457.     if (*s == '_' && s[1] == '_') break;
  458.   if (*s != 0) GNU_xref_ref (fndecl, name);
  459.  
  460.   fprintf (xref_file, "CAL %s %d %s %s\n",
  461.        filename (xf), lineno, name, fctname (fndecl));
  462. }
  463.  
  464. /* Output cross-reference info about FNDECL.  If non-NULL,
  465.    ARGS are the arguments for the function (i.e., before the FUNCTION_DECL
  466.    has been fully built).  */
  467.  
  468. void
  469. GNU_xref_function (fndecl, args)
  470.    tree fndecl;
  471.    tree args;
  472. {
  473.   XREF_FILE xf;
  474.   int ct;
  475.   char buf[1024];
  476.  
  477.   if (!doing_xref) return;
  478.   xf = find_file (input_filename);
  479.   if (xf == NULL) return;
  480.  
  481.   ct = 0;
  482.   buf[0] = 0;
  483.   if (args == NULL) args = DECL_ARGUMENTS (fndecl);
  484.  
  485.   GNU_xref_decl (NULL, fndecl);
  486.  
  487.   for ( ; args != NULL; args = TREE_CHAIN (args))
  488.     {
  489.       GNU_xref_decl (fndecl,args);
  490.       if (ct != 0) strcat (buf,",");
  491.       strcat (buf, declname (args));
  492.       ++ct;
  493.     }
  494.  
  495.   fprintf (xref_file, "PRC %s %d %s %d %d %s\n",
  496.        filename(xf), lineno, declname(fndecl),
  497.        (cur_scope != NULL ? cur_scope->lid : 0),
  498.        ct, buf);
  499. }
  500.  
  501. /* Output cross-reference info about an assignment to NAME.  */
  502.  
  503. void
  504. GNU_xref_assign(name)
  505.    tree name;
  506. {
  507.   XREF_FILE xf;
  508.  
  509.   if (!doing_xref) return;
  510.   xf = find_file(input_filename);
  511.   if (xf == NULL) return;
  512.  
  513.   gen_assign(xf, name);
  514. }
  515.  
  516. static void
  517. gen_assign(xf, name)
  518.    XREF_FILE xf;
  519.    tree name;
  520. {
  521.   String s;
  522.  
  523.   s = NULL;
  524.  
  525.   switch (TREE_CODE (name))
  526.     {
  527.     case IDENTIFIER_NODE :
  528.       s = IDENTIFIER_POINTER(name);
  529.       break;
  530.     case VAR_DECL :
  531.       s = declname(name);
  532.       break;
  533.     case COMPONENT_REF :
  534.       gen_assign(xf, TREE_OPERAND(name, 0));
  535.       gen_assign(xf, TREE_OPERAND(name, 1));
  536.       break;
  537.     case INDIRECT_REF :
  538.     case OFFSET_REF :
  539.     case ARRAY_REF :
  540.     case BUFFER_REF :
  541.       gen_assign(xf, TREE_OPERAND(name, 0));
  542.       break;
  543.     case COMPOUND_EXPR :
  544.       gen_assign(xf, TREE_OPERAND(name, 1));
  545.       break;
  546.       default :
  547.       break;
  548.     }
  549.  
  550.   if (s != NULL)
  551.     fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
  552. }
  553.  
  554. /* Output cross-reference info about a class hierarchy.
  555.    CLS is the class type of interest.  BASE is a baseclass
  556.    for CLS.  PUB and VIRT give the visibility info about
  557.    the class derivation.  FRND is nonzero iff BASE is a friend
  558.    of CLS.
  559.  
  560.    ??? Needs to handle nested classes.  */
  561. void
  562. GNU_xref_hier(cls, base, pub, virt, frnd)
  563.    String cls;
  564.    String base;
  565.    int pub;
  566.    int virt;
  567.    int frnd;
  568. {
  569.   XREF_FILE xf;
  570.  
  571.   if (!doing_xref) return;
  572.   xf = find_file(input_filename);
  573.   if (xf == NULL) return;
  574.  
  575.   fprintf(xref_file, "HIE %s %d %s %s %d %d %d\n",
  576.       filename(xf), lineno, cls, base, pub, virt, frnd);
  577. }
  578.  
  579. /* Output cross-reference info about class members.  CLS
  580.    is the containing type; FLD is the class member.  */
  581.  
  582. void
  583. GNU_xref_member(cls, fld)
  584.    tree cls;
  585.    tree fld;
  586. {
  587.   XREF_FILE xf;
  588.   String prot;
  589.   Integer confg, pure;
  590.   String d;
  591.   Integer i;
  592.   char buf[1024], bufa[1024];
  593.  
  594.   if (!doing_xref) return;
  595.   xf = find_file(fld->decl.filename);
  596.   if (xf == NULL) return;
  597.  
  598.   if (TREE_PRIVATE (fld)) prot = "PRIVATE";
  599.   else if (TREE_PROTECTED(fld)) prot = "PROTECTED";
  600.   else prot = "PUBLIC";
  601.  
  602.   confg = 0;
  603.   if (TREE_CODE (fld) == FUNCTION_DECL && DECL_CONST_MEMFUNC_P(fld))
  604.     confg = 1;
  605.   else if (TREE_CODE (fld) == CONST_DECL)
  606.     confg = 1;
  607.  
  608.   pure = 0;
  609.   if (TREE_CODE (fld) == FUNCTION_DECL && DECL_ABSTRACT_VIRTUAL_P(fld))
  610.     pure = 1;
  611.  
  612.   d = IDENTIFIER_POINTER(cls);
  613.   sprintf(buf, "%d%s", strlen(d), d);
  614.   i = strlen(buf);
  615.   strcpy(bufa, declname(fld));
  616.  
  617. #ifdef XREF_SHORT_MEMBER_NAMES
  618.   for (p = &bufa[1]; *p != 0; ++p)
  619.     {
  620.       if (p[0] == '_' && p[1] == '_' && p[2] >= '0' && p[2] <= '9') {
  621.     if (strncmp(&p[2], buf, i) == 0) *p = 0;
  622.     break;
  623.       }
  624.       else if (p[0] == '_' && p[1] == '_' && p[2] == 'C' && p[3] >= '0' && p[3] <= '9') {
  625.     if (strncmp(&p[3], buf, i) == 0) *p = 0;
  626.     break;
  627.       }
  628.     }
  629. #endif
  630.  
  631.   fprintf(xref_file, "MEM %s %d %s %s %s %d %d %d %d %d %d %d\n",
  632.       filename(xf), fld->decl.linenum, d,  bufa,  prot,
  633.       (TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1),
  634.       (DECL_INLINE (fld) ? 1 : 0),
  635.       (DECL_FRIEND_P(fld) ? 1 : 0),
  636.       (DECL_VINDEX(fld) ? 1 : 0),
  637.       (TREE_STATIC(fld) ? 1 : 0),
  638.       pure, confg);
  639. }
  640.  
  641. /* Find file entry given name.  */
  642.  
  643. static XREF_FILE
  644. find_file(name)
  645.    String name;
  646. {
  647.   XREF_FILE xf;
  648.  
  649.   for (xf = all_files; xf != NULL; xf = xf->next) {
  650.     if (STREQL(name, xf->name)) break;
  651.   }
  652.  
  653.   return xf;
  654. }
  655.  
  656. /* Return filename for output purposes.  */
  657.  
  658. static String
  659. filename(xf)
  660.    XREF_FILE xf;
  661. {
  662.   if (xf == NULL) {
  663.     last_file = NULL;
  664.     return "*";
  665.   }
  666.  
  667.   if (last_file == xf) return "*";
  668.  
  669.   last_file = xf;
  670.  
  671.   return xf->outname;
  672. }
  673.  
  674. /* Return function name for output purposes.  */
  675.  
  676. static String
  677. fctname(fndecl)
  678.    tree fndecl;
  679. {
  680.   extern char * declname();
  681.   static char fctbuf[1024];
  682.   String s;
  683.  
  684.   if (fndecl == NULL && last_fndecl == NULL) return "*";
  685.  
  686.   if (fndecl == NULL)
  687.     {
  688.       last_fndecl = NULL;
  689.       return "*TOP*";
  690.     }
  691.  
  692.   if (fndecl == last_fndecl) return "*";
  693.  
  694.   last_fndecl = fndecl;
  695.  
  696.   s = declname(fndecl);
  697.   s = fixname(s, fctbuf);
  698.  
  699.   return s;
  700. }
  701.  
  702. /* Return decl name for output purposes.  */
  703.  
  704. static String
  705. declname(dcl)
  706.    tree dcl;
  707. {
  708.   if (DECL_NAME (dcl) == NULL) return "?";
  709.  
  710.   if (DECL_ASSEMBLER_NAME (dcl))
  711.     return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (dcl));
  712.   else
  713.     return IDENTIFIER_POINTER (DECL_NAME (dcl));
  714. }
  715.  
  716. /* Simplify a type string by removing unneeded parenthesis.  */
  717.  
  718. static void
  719. simplify_type(typ)
  720.    String typ;
  721. {
  722.   String s;
  723.   Integer lvl, i;
  724.  
  725.   i = strlen(typ);
  726.   while (i > 0 && isspace(typ[i-1])) typ[--i] = 0;
  727.  
  728.   if (i > 7 && STREQL(&typ[i-5], "const"))
  729.     {
  730.       typ[i-5] = 0;
  731.       i -= 5;
  732.     }
  733.  
  734.   if (typ[i-1] != ')') return;
  735.  
  736.   s = &typ[i-2];
  737.   lvl = 1;
  738.   while (*s != 0) {
  739.     if (*s == ')') ++lvl;
  740.     else if (*s == '(')
  741.       {
  742.     --lvl;
  743.     if (lvl == 0)
  744.       {
  745.         s[1] = ')';
  746.         s[2] = 0;
  747.         break;
  748.       }
  749.       }
  750.     --s;
  751.   }
  752.  
  753.   if (*s != 0 && s[-1] == ')')
  754.     {
  755.       --s;
  756.       --s;
  757.       if (*s == '(') s[2] = 0;
  758.       else if (*s == ':') {
  759.     while (*s != '(') --s;
  760.     s[1] = ')';
  761.     s[2] = 0;
  762.       }
  763.     }
  764. }
  765.  
  766. /* Fixup a function name (take care of embedded spaces).  */
  767.  
  768. static String
  769. fixname(nam, buf)
  770.    String nam;
  771.    String buf;
  772. {
  773.   String s, t;
  774.   int fg;
  775.  
  776.   s = nam;
  777.   t = buf;
  778.   fg = 0;
  779.  
  780.   while (*s != 0)
  781.     {
  782.       if (*s == ' ')
  783.     {
  784.       *t++ = '\36';
  785.       ++fg;
  786.     }
  787.       else *t++ = *s;
  788.       ++s;
  789.     }
  790.   *t = 0;
  791.  
  792.   if (fg == 0) return nam;
  793.  
  794.   return buf;
  795. }
  796.  
  797. /* Open file for xrefing.  */
  798.  
  799. static void
  800. open_xref_file(file)
  801.    String file;
  802. {
  803.   String s, t;
  804.  
  805. #ifdef XREF_FILE_NAME
  806.   XREF_FILE_NAME (xref_name, file);
  807. #else
  808.   s = rindex (file, '/');
  809.   if (s == NULL)
  810.     sprintf (xref_name, ".%s.gxref", file);
  811.   else
  812.     {
  813.       ++s;
  814.       strcpy (xref_name, file);
  815.       t = rindex (xref_name, '/');
  816.       ++t;
  817.       *t++ = '.';
  818.       strcpy (t, s);
  819.       strcat (t, ".gxref");
  820.     }
  821. #endif /* no XREF_FILE_NAME */
  822.  
  823.   xref_file = fopen(xref_name, "w");
  824.  
  825.   if (xref_file == NULL)
  826.     {
  827.       error("Can't create cross-reference file `%s'", xref_name);
  828.       doing_xref = 0;
  829.     }
  830. }
  831.