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