1 /*
2 *   Copyright (c) 2016, Szymon Tomasz Stefanek
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 functions for parsing and scanning C++ source files
8 */
9 
10 #include "cxx_debug.h"
11 
12 #ifdef CXX_DO_DEBUGGING
13 
14 #include "trashbox.h"
15 #include "cxx_parser_internal.h"
16 #include "cxx_scope.h"
17 
18 static void cxxDebugDumpToken0 (CXXToken *pToken,
19 								struct circularRefChecker *pTokenChecker,
20 								struct circularRefChecker *pChainChecker,
21 								bool top_level);
22 
cxxDebugDumpChain0(CXXTokenChain * pChain,struct circularRefChecker * pTokenChecker,struct circularRefChecker * pChainChecker,bool top_level)23 static void cxxDebugDumpChain0 (CXXTokenChain *pChain,
24 								struct circularRefChecker *pTokenChecker,
25 								struct circularRefChecker *pChainChecker,
26 								bool top_level)
27 {
28 	int backref;
29 
30 	if (top_level)
31 	{
32 		debugIndent ();
33 		fprintf (stderr, "<chain ");
34 	}
35 	else if (pChain == NULL)
36 	{
37 		fprintf (stderr, "NULL\n");
38 		return;
39 	}
40 	else
41 	{
42 		fprintf (stderr, "<");
43 	}
44 
45 	backref = circularRefCheckerCheck (pChainChecker, pChain);
46 	if (backref)
47 	{
48 		fprintf (stderr, "*C#%d>\n", backref);
49 		return;
50 	}
51 
52 	backref = circularRefCheckerGetCurrent (pChainChecker);
53 
54 	fprintf (stderr, "[%d %p&C#%d]\n", pChain->iCount, pChain, backref);
55 
56 	debugInc();
57 	debugIndent ();
58 	cxxDebugDumpToken0 (pChain->pHead, pTokenChecker, pChainChecker, false);
59 	debugDec();
60 
61 	debugIndent ();
62 	fprintf (stderr, ">\n");
63 }
64 
cxxDebugDumpToken0(CXXToken * pToken,struct circularRefChecker * pTokenChecker,struct circularRefChecker * pChainChecker,bool top_level)65 static void cxxDebugDumpToken0 (CXXToken *pToken,
66 								struct circularRefChecker *pTokenChecker,
67 								struct circularRefChecker *pChainChecker,
68 								bool top_level)
69 {
70 	int backref;
71 
72 	if (top_level)
73 	{
74 		debugIndent ();
75 		fprintf (stderr, "<token ");
76 	}
77 	else if (pToken == NULL)
78 	{
79 		fprintf (stderr, "NULL\n");
80 		return;
81 	}
82 	else
83 	{
84 		fprintf (stderr, "<");
85 	}
86 
87 	backref = circularRefCheckerCheck (pTokenChecker, pToken);
88 	if (backref)
89 	{
90 		fprintf (stderr, "*T#%d>\n", backref);
91 		return;
92 	}
93 
94 	backref = circularRefCheckerGetCurrent (pTokenChecker);
95 
96 	fprintf (stderr, "\"%s\": [%s %p &T#%d]\n",
97 			 vStringValue (pToken->pszWord),
98 			 cxxDebugTypeDecode (pToken->eType), pToken, backref);
99 
100 	debugIndent ();
101 	fprintf (stderr, "  chain: ");
102 	debugInc();
103 	cxxDebugDumpChain0 (pToken->pChain, pTokenChecker, pTokenChecker, false);
104 	debugDec();
105 
106 	debugIndent ();
107 	fprintf (stderr, "  next: ");
108 	debugInc();
109 	cxxDebugDumpToken0 (pToken->pNext, pTokenChecker, pTokenChecker, false);
110 	debugDec();
111 
112 	debugIndent ();
113 	fprintf (stderr, "  prev: ");
114 	debugInc();
115 	cxxDebugDumpToken0 (pToken->pPrev, pTokenChecker, pTokenChecker, false);
116 	debugDec();
117 
118 	debugIndent ();
119 	fprintf (stderr, ">\n");
120 }
121 
122 typedef void (* cxxDebugDumpCommonFunc)(void *,
123 										struct circularRefChecker *,
124 										struct circularRefChecker *,
125 										bool);
cxxDebugDumpCommon(void * data,void (* func)(void *,struct circularRefChecker *,struct circularRefChecker *,bool))126 void cxxDebugDumpCommon (void *data,
127 						 void (* func)(void *,
128 									   struct circularRefChecker *,
129 									   struct circularRefChecker *,
130 									   bool))
131 {
132 	static struct circularRefChecker *pTokenChecker;
133 	static struct circularRefChecker *pChainChecker;
134 
135 	if (!pTokenChecker)
136 	{
137 		pTokenChecker = circularRefCheckerNew();
138 		DEFAULT_TRASH_BOX(pTokenChecker, (TrashBoxDestroyItemProc)circularRefCheckerDestroy);
139 	}
140 
141 	if (!pChainChecker)
142 	{
143 		pChainChecker = circularRefCheckerNew();
144 		DEFAULT_TRASH_BOX(pChainChecker, (TrashBoxDestroyItemProc)circularRefCheckerDestroy);
145 	}
146 
147 	func(data, pTokenChecker, pChainChecker, true);
148 
149 	circularRefCheckClear (pTokenChecker);
150 	circularRefCheckClear (pChainChecker);
151 }
152 
cxxDebugDumpToken(CXXToken * pToken)153 void cxxDebugDumpToken (CXXToken *pToken)
154 {
155 	cxxDebugDumpCommon (pToken, (cxxDebugDumpCommonFunc)cxxDebugDumpToken0);
156 }
157 
cxxDebugDumpChain(CXXTokenChain * pChain)158 void cxxDebugDumpChain (CXXTokenChain *pChain)
159 {
160 	cxxDebugDumpCommon (pChain, (cxxDebugDumpCommonFunc)cxxDebugDumpChain0);
161 }
162 
cxxDebugScopeDecode(enum CXXScopeType scope)163 const char* cxxDebugScopeDecode(enum CXXScopeType scope)
164 {
165 	const char * table[] = {
166 		[CXXScopeTypeFunction]  = "function",
167 		[CXXScopeTypeNamespace] = "namespace",
168 		[CXXScopeTypeClass] = "class",
169 		[CXXScopeTypeEnum] = "enum",
170 		[CXXScopeTypeUnion] = "union",
171 		[CXXScopeTypeStruct] = "struct",
172 		[CXXScopeTypeVariable] = "variable",
173 		[CXXScopeTypePrototype]  = "prototype",
174 		[CXXScopeTypeTypedef] = "typedef",
175 	};
176 	if (CXXScopeTypeLAST > scope)
177 		return table[scope];
178 	else
179 		return NULL;
180 }
181 
182 #endif
183