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