source: trunk/third/gcc/cp/xref.c @ 8834

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