1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include <precomp.h>
23 #include "preproc.hxx"
24 
25 
26 // NOT FULLY DEFINED SERVICES
27 #include <cosv/tpl/tpltools.hxx>
28 #include "all_toks.hxx"
29 #include "defdescr.hxx"
30 #include <tools/tkpchars.hxx>
31 #include "c_rcode.hxx"
32 
33 
34 namespace cpp
35 {
36 
37 
38 PreProcessor::F_TOKENPROC PreProcessor::aTokProcs[PreProcessor::state_MAX] =
39     {
40         &PreProcessor::On_plain,
41         &PreProcessor::On_expect_macro_bracket_left,
42         &PreProcessor::On_expect_macro_param
43     };
44 
45 
PreProcessor()46 PreProcessor::PreProcessor()
47     :   pCppExplorer(0),
48         pSourceText(0),
49         pCurValidDefines(0),
50         // aTokens,
51         eState(plain),
52         pCurMacro(0),
53         dpCurMacroName(0),
54         // aCurMacroParams,
55         aCurParamText(60000),
56         nBracketInParameterCounter(0)
57         // aBlockedMacroNames
58 {
59 }
60 
~PreProcessor()61 PreProcessor::~PreProcessor()
62 {
63 }
64 
65 void
AssignPartners(CodeExplorer & o_rCodeExplorer,CharacterSource & o_rCharSource,const MacroMap & i_rCurValidDefines)66 PreProcessor::AssignPartners( CodeExplorer &      o_rCodeExplorer,
67                               CharacterSource &   o_rCharSource,
68                               const MacroMap &    i_rCurValidDefines )
69 {
70     pCppExplorer = &o_rCodeExplorer;
71     pSourceText = &o_rCharSource;
72     pCurValidDefines = &i_rCurValidDefines;
73 }
74 
75 void
Process_Token(cpp::Token & let_drToken)76 PreProcessor::Process_Token( cpp::Token & let_drToken )
77 {
78     csv_assert(pCppExplorer != 0);  // Implies pSourceText and pCurValidDefines.
79 
80     (this->*aTokProcs[eState])(let_drToken);
81 }
82 
83 void
On_plain(cpp::Token & let_drToken)84 PreProcessor::On_plain( cpp::Token & let_drToken )
85 {
86     if ( let_drToken.TypeId() == Tid_Identifier )
87     {
88         if (CheckForDefine(let_drToken))
89             return;
90     }
91 
92     pCppExplorer->Process_Token(let_drToken);
93 }
94 
95 void
On_expect_macro_bracket_left(cpp::Token & let_drToken)96 PreProcessor::On_expect_macro_bracket_left( cpp::Token & let_drToken )
97 {
98     if ( let_drToken.TypeId() == Tid_Bracket_Left )
99     {
100         aCurParamText.seekp(0);
101         eState = expect_macro_param;
102     }
103     else
104     {
105         pCppExplorer->Process_Token(*dpCurMacroName);
106         dpCurMacroName = 0;
107         pCppExplorer->Process_Token(let_drToken);
108         eState = plain;
109     }
110 }
111 
112 void
On_expect_macro_param(cpp::Token & let_drToken)113 PreProcessor::On_expect_macro_param( cpp::Token & let_drToken )
114 {
115     if ( let_drToken.TypeId() == Tid_Bracket_Left )
116         nBracketInParameterCounter++;
117     else if ( let_drToken.TypeId() == Tid_Bracket_Right )
118     {
119         if ( nBracketInParameterCounter > 0 )
120             nBracketInParameterCounter--;
121         else
122         {
123             if ( NOT csv::no_str(aCurParamText.c_str()) )
124             {
125                 aCurMacroParams.push_back( String(aCurParamText.c_str()) );
126             }
127             csv_assert( aCurMacroParams.size() == pCurMacro->ParamCount() );
128 
129             InterpretMacro();
130             eState = plain;
131             return;
132         }
133     }
134     else if ( let_drToken.TypeId() == Tid_Comma AND nBracketInParameterCounter == 0 )
135     {
136         aCurMacroParams.push_back( String (aCurParamText.c_str()) );
137         aCurParamText.seekp(0);
138         return;
139     }
140 
141     // KORR_FUTURE:
142     //  If in future whitespace is parsed also, that should match exactly and the
143     //  safety spaces, " ", here should be removed.
144     aCurParamText << let_drToken.Text() << " ";
145 }
146 
147 bool
CheckForDefine(cpp::Token & let_drToken)148 PreProcessor::CheckForDefine( cpp::Token & let_drToken )
149 {
150     String  sTokenText(let_drToken.Text());
151  	pCurMacro = csv::value_from_map( *pCurValidDefines, sTokenText );
152     if (pCurMacro == 0 )
153         return false;
154     for ( StringVector::const_iterator it = aBlockedMacroNames.begin();
155           it != aBlockedMacroNames.end();
156           ++it )
157     {
158         if ( strcmp( (*it).c_str(), let_drToken.Text() ) == 0 )
159             return false;
160     }
161 
162     if ( pCurMacro->DefineType() == DefineDescription::type_define )
163     {
164         delete &let_drToken;
165 
166         aCurParamText.seekp(0);
167         pCurMacro->GetDefineText(aCurParamText);
168 
169         if ( aCurParamText.tellp() > 1 )
170             pSourceText->InsertTextAtCurPos(aCurParamText.c_str());
171     }
172     else // ( pCurMacro->DefineType() == DefineDescription::type_macro )
173     {
174         dpCurMacroName = &let_drToken;
175         eState = expect_macro_bracket_left;
176         csv::erase_container( aCurMacroParams );
177         aCurParamText.seekp(0);
178         nBracketInParameterCounter = 0;
179     }  // endif
180 
181     return true;
182 }
183 
184 void
UnblockMacro(const char * i_sMacroName)185 PreProcessor::UnblockMacro( const char * i_sMacroName )
186 {
187     for ( StringVector::iterator it = aBlockedMacroNames.begin();
188           it != aBlockedMacroNames.end();
189           ++it )
190     {
191         if ( strcmp( (*it), i_sMacroName ) == 0 )
192         {
193             aBlockedMacroNames.erase(it);
194             break;
195         }
196     }   /// end for
197 }
198 
199 void
InterpretMacro()200 PreProcessor::InterpretMacro()
201 {
202     aCurParamText.seekp(0);
203     pCurMacro->GetMacroText(aCurParamText, aCurMacroParams);
204 
205     if ( NOT csv::no_str(aCurParamText.c_str()) )
206     {
207         aCurParamText.seekp(-1, csv::cur);
208         aCurParamText << " #unblock-" << dpCurMacroName->Text() << " ";
209 
210         pSourceText->InsertTextAtCurPos(aCurParamText.c_str());
211         String  sCurMacroName(dpCurMacroName->Text());
212         aBlockedMacroNames.insert( aBlockedMacroNames.begin(), sCurMacroName );
213     }
214 
215     delete dpCurMacroName;
216     dpCurMacroName = 0;
217     pCurMacro = 0;
218     csv::erase_container(aCurMacroParams);
219     aCurParamText.seekp(0);
220 }
221 
222 
223 }   // end namespace cpp
224 
225 
226