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