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_token.h"
11
12 #include "routines.h"
13 #include "vstring.h"
14 #include "read.h"
15 #include "objpool.h"
16
17 #include "cxx_token_chain.h"
18 #include "cxx_debug.h"
19 #include "cxx_keyword.h"
20 #include "cxx_tag.h"
21
22 #define CXX_TOKEN_POOL_MAXIMUM_SIZE 8192
23
24 static objPool * g_pTokenPool = NULL;
25
26 void cxxTokenForceDestroy(CXXToken * t);
27
createToken(void * createArg CTAGS_ATTR_UNUSED)28 static CXXToken *createToken(void *createArg CTAGS_ATTR_UNUSED)
29 {
30 CXXToken *t = xMalloc(1, CXXToken);
31 // we almost always want a string, and since this token
32 // is being reused..well.. we always want it
33 t->pszWord = vStringNew();
34 return t;
35 }
36
deleteToken(CXXToken * token)37 static void deleteToken(CXXToken *token)
38 {
39 vStringDelete(token->pszWord);
40 eFree(token);
41 }
42
clearToken(CXXToken * t)43 static void clearToken(CXXToken *t)
44 {
45 CXX_DEBUG_ASSERT(t->pszWord,"The string shouldn't have been destroyed");
46
47 // this won't actually release memory (but we're taking care
48 // to do not create very large strings)
49 vStringClear(t->pszWord);
50
51 t->bFollowedBySpace = false;
52
53 t->pChain = NULL;
54 t->pNext = NULL;
55 t->pPrev = NULL;
56 }
57
cxxTokenAPIInit(void)58 void cxxTokenAPIInit(void)
59 {
60 g_pTokenPool = objPoolNew(CXX_TOKEN_POOL_MAXIMUM_SIZE,
61 (objPoolCreateFunc)createToken, (objPoolDeleteFunc)deleteToken,
62 (objPoolClearFunc)clearToken,
63 NULL);
64 }
65
cxxTokenAPINewFile(void)66 void cxxTokenAPINewFile(void)
67 {
68 /* Stub */
69 }
70
cxxTokenAPIDone(void)71 void cxxTokenAPIDone(void)
72 {
73 objPoolDelete (g_pTokenPool);
74 }
75
cxxTokenCreate(void)76 CXXToken * cxxTokenCreate(void)
77 {
78 return objPoolGet (g_pTokenPool);
79 }
80
cxxTokenDestroy(CXXToken * t)81 void cxxTokenDestroy(CXXToken * t)
82 {
83 if(!t)
84 return;
85
86 if(t->pChain)
87 {
88 cxxTokenChainDestroy(t->pChain);
89 t->pChain = NULL;
90 }
91
92 objPoolPut (g_pTokenPool, t);
93 }
94
cxxTokenForceDestroy(CXXToken * t)95 void cxxTokenForceDestroy(CXXToken * t)
96 {
97 if(!t)
98 return;
99
100 if(t->pChain)
101 {
102 cxxTokenChainDestroy(t->pChain);
103 t->pChain = NULL;
104 }
105
106 CXX_DEBUG_ASSERT(t->pszWord,"There should be a word here");
107
108 vStringDelete(t->pszWord);
109
110 eFree(t);
111 }
112
cxxTokenCopy(CXXToken * pToken)113 CXXToken * cxxTokenCopy(CXXToken * pToken)
114 {
115 CXXToken * pRetToken = cxxTokenCreate();
116 pRetToken->iLineNumber = pToken->iLineNumber;
117 pRetToken->oFilePosition = pToken->oFilePosition;
118 pRetToken->eType = pToken->eType;
119 pRetToken->eKeyword = pToken->eKeyword;
120 pToken->bFollowedBySpace = pToken->bFollowedBySpace;
121 vStringCat(pRetToken->pszWord,pToken->pszWord);
122
123 return pRetToken;
124 }
125
cxxTokenCreateKeyword(int iLineNumber,MIOPos oFilePosition,CXXKeyword eKeyword)126 CXXToken * cxxTokenCreateKeyword(int iLineNumber,MIOPos oFilePosition,CXXKeyword eKeyword)
127 {
128 CXXToken * pToken = cxxTokenCreate();
129 pToken->iLineNumber = iLineNumber;
130 pToken->oFilePosition = oFilePosition;
131 pToken->eType = CXXTokenTypeKeyword;
132 pToken->eKeyword = eKeyword;
133 pToken->bFollowedBySpace = true;
134 vStringCatS(pToken->pszWord,cxxKeywordName(eKeyword));
135
136 return pToken;
137 }
138
139
cxxTokenCreateAnonymousIdentifier(unsigned int uTagKind)140 CXXToken * cxxTokenCreateAnonymousIdentifier(unsigned int uTagKind)
141 {
142 CXXToken * t = cxxTokenCreate();
143
144 anonGenerate (t->pszWord, "__anon", uTagKind);
145 t->eType = CXXTokenTypeIdentifier;
146 t->bFollowedBySpace = true;
147 t->iLineNumber = getInputLineNumber();
148 t->oFilePosition = getInputFilePosition();
149
150 return t;
151 }
152
cxxTokenAppendToString(vString * s,CXXToken * t)153 void cxxTokenAppendToString(vString * s,CXXToken * t)
154 {
155 switch(t->eType)
156 {
157 case CXXTokenTypeParenthesisChain:
158 case CXXTokenTypeSquareParenthesisChain:
159 case CXXTokenTypeBracketChain:
160 case CXXTokenTypeAngleBracketChain:
161 CXX_DEBUG_ASSERT(t->pChain,"This token should have a nested chain!");
162 cxxTokenChainJoinInString(t->pChain,s,NULL,0);
163 break;
164 default:
165 vStringCat(s,t->pszWord);
166 break;
167 }
168 }
169
cxxTokenReduceBackward(CXXToken * pStart)170 void cxxTokenReduceBackward (CXXToken *pStart)
171 {
172 enum CXXTokenType eSentinelType = pStart->eType >> 4;
173 CXXToken *pTmp = pStart->pPrev;
174 CXXToken *pReducingCandidate;
175
176 while (pTmp && (!cxxTokenTypeIsOneOf (pTmp, eSentinelType)))
177 {
178 pReducingCandidate = pTmp;
179 pTmp = pTmp->pPrev;
180 pTmp->pNext = pReducingCandidate->pNext;
181 pReducingCandidate->pNext->pPrev = pTmp;
182 CXX_DEBUG_PRINT("reduce inner token: %p",pReducingCandidate);
183 cxxTokenDestroy (pReducingCandidate);
184 }
185 }
186