xref: /Universal-ctags/parsers/cxx/cxx_token.c (revision a22956a314b4dfff7baf76fca3d0b036b1930ac4)
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