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_scope.h"
11
12 #include "vstring.h"
13 #include "debug.h"
14
15 #include "cxx_tag.h"
16 #include "cxx_debug.h"
17 #include "cxx_token_chain.h"
18
19 #ifdef CXX_DO_DEBUGGING
20 #include "cxx_parser_internal.h"
21 #endif
22
23 // The tokens defining current scope
24 static CXXTokenChain * g_pScope = NULL;
25 static vString * g_szScopeName = NULL;
26 static bool g_bScopeNameDirty = true;
27
cxxScopeInit(void)28 void cxxScopeInit(void)
29 {
30 g_pScope = cxxTokenChainCreate();
31 }
32
cxxScopeDone(void)33 void cxxScopeDone(void)
34 {
35 cxxTokenChainDestroy(g_pScope);
36 if(g_szScopeName)
37 {
38 vStringDelete(g_szScopeName);
39 g_szScopeName = NULL;
40 }
41 }
42
cxxScopeClear(void)43 void cxxScopeClear(void)
44 {
45 if(g_pScope)
46 cxxTokenChainClear(g_pScope);
47 if(g_szScopeName)
48 {
49 vStringDelete(g_szScopeName);
50 g_szScopeName = NULL;
51 }
52 }
53
cxxScopeIsGlobal(void)54 bool cxxScopeIsGlobal(void)
55 {
56 return (g_pScope->iCount < 1);
57 }
58
cxxScopeGetType(void)59 enum CXXScopeType cxxScopeGetType(void)
60 {
61 if(g_pScope->iCount < 1)
62 return CXXScopeTypeNamespace;
63 return (enum CXXScopeType)g_pScope->pTail->uInternalScopeType;
64 }
65
cxxScopeGetVariableKind(void)66 unsigned int cxxScopeGetVariableKind(void)
67 {
68 switch(cxxScopeGetType())
69 {
70 case CXXScopeTypeClass:
71 case CXXScopeTypeUnion:
72 case CXXScopeTypeStruct:
73 return CXXTagKindMEMBER;
74 break;
75 case CXXScopeTypeFunction:
76 return CXXTagKindLOCAL;
77 break;
78 //case CXXScopeTypePrototype:
79 //case CXXScopeTypeNamespace:
80 //case CXXScopeTypeEnum:
81 default:
82 // fall down
83 break;
84 }
85 return CXXTagKindVARIABLE;
86 }
87
88
cxxScopeGetKind(void)89 unsigned int cxxScopeGetKind(void)
90 {
91 CXX_DEBUG_ASSERT(g_pScope->iCount >= 0,"Must not be called in global scope");
92
93 switch(g_pScope->pTail->uInternalScopeType)
94 {
95 case CXXScopeTypeNamespace:
96 CXX_DEBUG_ASSERT(cxxParserCurrentLanguageIsCPP(),"C++ only");
97 return CXXTagCPPKindNAMESPACE;
98 case CXXScopeTypeClass:
99 CXX_DEBUG_ASSERT(cxxParserCurrentLanguageIsCPP(),"C++ only");
100 return CXXTagCPPKindCLASS;
101 case CXXScopeTypeEnum:
102 return CXXTagKindENUM;
103 case CXXScopeTypeFunction:
104 return CXXTagKindFUNCTION;
105 case CXXScopeTypePrototype:
106 return CXXTagKindPROTOTYPE;
107 case CXXScopeTypeStruct:
108 return CXXTagKindSTRUCT;
109 case CXXScopeTypeUnion:
110 return CXXTagKindUNION;
111 case CXXScopeTypeVariable:
112 return CXXTagKindVARIABLE;
113 case CXXScopeTypeTypedef:
114 return CXXTagKindTYPEDEF;
115 default:
116 CXX_DEBUG_ASSERT(false,"Unhandled scope type!");
117 break;
118 }
119
120 return CXXTagKindFUNCTION;
121 }
122
123
cxxScopeGetAccess(void)124 enum CXXScopeAccess cxxScopeGetAccess(void)
125 {
126 if(g_pScope->iCount < 1)
127 return CXXScopeAccessUnknown;
128 return (enum CXXScopeAccess)g_pScope->pTail->uInternalScopeAccess;
129 }
130
cxxScopeGetName(void)131 const char * cxxScopeGetName(void)
132 {
133 if(g_pScope->iCount < 1)
134 return NULL;
135 return vStringValue(g_pScope->pTail->pszWord);
136 }
137
cxxScopeGetSize(void)138 int cxxScopeGetSize(void)
139 {
140 return g_pScope->iCount;
141 }
142
cxxScopeGetFullName(void)143 const char * cxxScopeGetFullName(void)
144 {
145 if(!g_bScopeNameDirty)
146 return g_szScopeName ? g_szScopeName->buffer : NULL;
147
148 if(g_pScope->iCount < 1)
149 {
150 g_bScopeNameDirty = false;
151 return NULL;
152 }
153
154 if(g_szScopeName)
155 vStringClear(g_szScopeName);
156 else
157 g_szScopeName = vStringNew();
158
159 cxxTokenChainJoinInString(
160 g_pScope,
161 g_szScopeName,
162 "::",
163 CXXTokenChainJoinNoTrailingSpaces
164 );
165
166 g_bScopeNameDirty = false;
167 return g_szScopeName->buffer;
168 }
169
cxxScopeGetFullNameAsString(void)170 vString * cxxScopeGetFullNameAsString(void)
171 {
172 vString * ret;
173
174 if(!g_bScopeNameDirty)
175 {
176 ret = g_szScopeName;
177 g_szScopeName = NULL;
178 g_bScopeNameDirty = true;
179 return ret;
180 }
181
182 if(g_pScope->iCount < 1)
183 return NULL;
184
185 if(g_szScopeName)
186 vStringClear(g_szScopeName);
187 else
188 g_szScopeName = vStringNew();
189
190 cxxTokenChainJoinInString(
191 g_pScope,
192 g_szScopeName,
193 "::",
194 CXXTokenChainJoinNoTrailingSpaces
195 );
196
197 ret = g_szScopeName;
198 g_szScopeName = NULL;
199 return ret;
200 }
201
cxxScopeGetFullNameExceptLastComponentAsString(void)202 vString * cxxScopeGetFullNameExceptLastComponentAsString(void)
203 {
204 if(g_pScope->iCount < 2)
205 return NULL;
206
207 return cxxTokenChainJoinRange(
208 g_pScope->pHead,
209 g_pScope->pTail->pPrev,
210 "::",
211 CXXTokenChainJoinNoTrailingSpaces
212 );
213 }
214
215
cxxScopeSetAccess(enum CXXScopeAccess eAccess)216 void cxxScopeSetAccess(enum CXXScopeAccess eAccess)
217 {
218 if(g_pScope->iCount < 1)
219 return; // warning?
220 g_pScope->pTail->uInternalScopeAccess = (unsigned char)eAccess;
221 }
222
cxxScopePushTop(CXXToken * t)223 void cxxScopePushTop(CXXToken * t)
224 {
225 CXX_DEBUG_ASSERT(
226 t->eType == CXXTokenTypeIdentifier,
227 "The scope name must be an identifier"
228 );
229 CXX_DEBUG_ASSERT(
230 t->pszWord,
231 "The scope name should have a text"
232 );
233
234 cxxTokenChainAppend(g_pScope,t);
235 g_bScopeNameDirty = true;
236
237 #ifdef CXX_DO_DEBUGGING
238 const char * szScopeName = cxxScopeGetFullName();
239
240 CXX_DEBUG_PRINT("Pushed scope: '%s'",szScopeName ? szScopeName : "");
241 #endif
242 }
243
cxxScopeTakeTop(void)244 CXXToken * cxxScopeTakeTop(void)
245 {
246 CXX_DEBUG_ASSERT(
247 g_pScope->iCount > 0,
248 "When popping as scope there must be a scope to pop"
249 );
250
251 CXXToken * t = cxxTokenChainTakeLast(g_pScope);
252 g_bScopeNameDirty = true;
253
254 #ifdef CXX_DO_DEBUGGING
255 const char * szScopeName = cxxScopeGetFullName();
256
257 CXX_DEBUG_PRINT("Popped scope: '%s'",szScopeName ? szScopeName : "");
258 #endif
259 return t;
260 }
261
cxxScopePush(CXXToken * t,enum CXXScopeType eScopeType,enum CXXScopeAccess eInitialAccess)262 void cxxScopePush(
263 CXXToken * t,
264 enum CXXScopeType eScopeType,
265 enum CXXScopeAccess eInitialAccess
266 )
267 {
268 t->uInternalScopeType = (unsigned char)eScopeType;
269 t->uInternalScopeAccess = (unsigned char)eInitialAccess;
270 cxxScopePushTop(t);
271 }
272
cxxScopePop(void)273 void cxxScopePop(void)
274 {
275 cxxTokenDestroy(cxxScopeTakeTop());
276 }
277