xref: /Universal-ctags/main/debug.c (revision b5df137e38436c77ae08476f2b68e2c170dae1d0)
1 /*
2 *   Copyright (c) 1996-2002, Darren Hiebert
3 *
4 *   This source code is released for free distribution under the terms of the
5 *   GNU General Public License version 2 or (at your option) any later version.
6 *
7 *   This module contains debugging functions.
8 */
9 
10 /*
11 *   INCLUDE FILES
12 */
13 #include "general.h"  /* must always come first */
14 
15 #include <ctype.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <string.h>
20 
21 #include "debug.h"
22 #include "entry_p.h"
23 #include "options.h"
24 #include "parse_p.h"
25 #include "read.h"
26 #include "read_p.h"
27 
28 /*
29 *   FUNCTION DEFINITIONS
30 */
31 
32 #ifdef DEBUG
33 #include "htable.h"
34 
35 
lineBreak(void)36 extern void lineBreak (void) {}  /* provides a line-specified break point */
37 
debugPrintf(const enum eDebugLevels level,const char * const format,...)38 extern void debugPrintf (
39 		const enum eDebugLevels level, const char *const format, ... )
40 {
41 	va_list ap;
42 
43 	va_start (ap, format);
44 	if (debug (level))
45 		vprintf (format, ap);
46 	fflush (stdout);
47 	va_end (ap);
48 }
49 
debugPutc(const int level,const int c)50 extern void debugPutc (const int level, const int c)
51 {
52 	if (debug (level)  &&  c != EOF)
53 	{
54 		     if (c == STRING_SYMBOL)  printf ("\"string\"");
55 		else if (c == CHAR_SYMBOL)    printf ("'c'");
56 		else                          putchar (c);
57 
58 		fflush (stdout);
59 	}
60 }
61 
debugParseNest(const bool increase,const unsigned int level)62 extern void debugParseNest (const bool increase, const unsigned int level)
63 {
64 	debugPrintf (DEBUG_PARSE, "<*%snesting:%d*>", increase ? "++" : "--", level);
65 }
66 
debugCppNest(const bool begin,const unsigned int level)67 extern void debugCppNest (const bool begin, const unsigned int level)
68 {
69 	debugPrintf (DEBUG_CPP, "<*cpp:%s level %d*>", begin ? "begin":"end", level);
70 }
71 
debugCppIgnore(const bool ignore)72 extern void debugCppIgnore (const bool ignore)
73 {
74 	debugPrintf (DEBUG_CPP, "<*cpp:%s ignore*>", ignore ? "begin":"end");
75 }
76 
debugEntry(const tagEntryInfo * const tag)77 extern void debugEntry (const tagEntryInfo *const tag)
78 {
79 	const char *const scope = tag->isFileScope ? "{fs}" : "";
80 
81 	if (debug (DEBUG_PARSE))
82 	{
83 		langType lang = (tag->extensionFields.scopeLangType == LANG_AUTO)
84 			? tag->langType
85 			: tag->extensionFields.scopeLangType;
86 		kindDefinition *scopeKindDef = getLanguageKind(lang,
87 													   tag->extensionFields.scopeKindIndex);
88 		printf ("<#%s%s:%s", scope, getTagKindName(tag), tag->name);
89 
90 		if (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX  &&
91 				tag->extensionFields.scopeName != NULL)
92 			printf (" [%s:%s]", scopeKindDef->name,
93 					tag->extensionFields.scopeName);
94 
95 		if (isFieldEnabled (FIELD_INHERITANCE) &&
96 				tag->extensionFields.inheritance != NULL)
97 			printf (" [inherits:%s]", tag->extensionFields.inheritance);
98 
99 		if (isFieldEnabled (FIELD_FILE_SCOPE) &&
100 				tag->isFileScope && ! isInputHeaderFile ())
101 			printf (" [file:]");
102 
103 		if (isFieldEnabled (FIELD_ACCESS) &&
104 				tag->extensionFields.access != NULL)
105 			printf (" [access:%s]", tag->extensionFields.access);
106 
107 		if (isFieldEnabled (FIELD_IMPLEMENTATION) &&
108 				tag->extensionFields.implementation != NULL)
109 			printf (" [imp:%s]", tag->extensionFields.implementation);
110 
111 		if (isFieldEnabled (FIELD_TYPE_REF) &&
112 				tag->extensionFields.typeRef [0] != NULL  &&
113 				tag->extensionFields.typeRef [1] != NULL)
114 			printf (" [%s:%s]", tag->extensionFields.typeRef [0],
115 					tag->extensionFields.typeRef [1]);
116 
117 		printf ("#>");
118 		fflush (stdout);
119 	}
120 }
121 
debugAssert(const char * assertion,const char * file,unsigned int line,const char * function)122 extern void debugAssert (const char *assertion, const char *file, unsigned int line, const char *function)
123 {
124 	fprintf(stderr, "ctags: %s:%u: %s%sAssertion `%s' failed.\n",
125 	        file, line,
126 	        function ? function : "", function ? ": " : "",
127 	        assertion);
128 	if (getInputFileName())
129 	{
130 		fprintf(stderr, "ctags: %s:%u: parsing %s:%lu as %s\n",
131 		        file, line,
132 		        getInputFileName(), getInputLineNumber(),
133 		        getInputLanguageName());
134 	}
135 	fflush(stderr);
136 	abort();
137 }
138 
139 static int debugScopeDepth;
140 #define DEBUG_INDENT_UNIT 4
141 
142 static char debugPrefix[DEBUG_INDENT_UNIT + 1];
143 
debugInit(void)144 extern void debugInit (void)
145 {
146 	memset(debugPrefix, ' ', DEBUG_INDENT_UNIT);
147 	debugPrefix[DEBUG_INDENT_UNIT] = '\0';
148 }
149 
debugIndent(void)150 extern void debugIndent(void)
151 {
152 	for(int i=0;i< debugScopeDepth;i++)
153 		fputs(debugPrefix, stderr);
154 }
155 
debugInc(void)156 extern void debugInc(void)
157 {
158 	debugScopeDepth++;
159 }
160 
debugDec(void)161 extern void debugDec(void)
162 {
163 	debugScopeDepth--;
164 	if(debugScopeDepth < 0)
165 		debugScopeDepth = 0;
166 }
167 
168 
169 
170 struct circularRefChecker {
171 	hashTable *visitTable;
172 	int counter;
173 };
174 
circularRefCheckerDestroy(struct circularRefChecker * checker)175 extern void circularRefCheckerDestroy (struct circularRefChecker * checker)
176 {
177 	hashTableDelete (checker->visitTable);
178 	checker->visitTable = NULL;
179 	eFree (checker);
180 }
181 
circularRefCheckerNew(void)182 extern struct circularRefChecker * circularRefCheckerNew (void)
183 {
184 	Assert (sizeof(void *) >= sizeof(int));
185 
186 	struct circularRefChecker *c = xMalloc (1, struct circularRefChecker);
187 
188 	c->visitTable = hashTableNew (17, hashPtrhash, hashPtreq, NULL, NULL);
189 	c->counter = 0;
190 
191 	return c;
192 }
193 
circularRefCheckerCheck(struct circularRefChecker * c,void * ptr)194 extern int circularRefCheckerCheck (struct circularRefChecker *c, void *ptr)
195 {
196 	union conv {
197 		int i;
198 		void *ptr;
199 	} v;
200 
201 	v.ptr = hashTableGetItem(c->visitTable, ptr);
202 	if (v.ptr)
203 		return v.i;
204 	else
205 	{
206 		v.i = ++c->counter;
207 		hashTablePutItem (c->visitTable, ptr, v.ptr);
208 		return 0;
209 	}
210 }
211 
circularRefCheckerGetCurrent(struct circularRefChecker * c)212 extern int circularRefCheckerGetCurrent (struct circularRefChecker *c)
213 {
214 	return c->counter;
215 }
216 
circularRefCheckClear(struct circularRefChecker * c)217 extern void circularRefCheckClear (struct circularRefChecker *c)
218 {
219 	hashTableClear (c->visitTable);
220 	c->counter = 0;
221 }
222 
223 #endif
224