home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cc-61.0.1 / cc / cplus-xref.c < prev    next >
C/C++ Source or Header  |  1991-06-03  |  17KB  |  811 lines

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