|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 * Parser for preprocessor definitions and include statements |
|
17 * |
|
18 */ |
|
19 package com.nokia.tracebuilder.source; |
|
20 |
|
21 import java.util.ArrayList; |
|
22 import java.util.Iterator; |
|
23 |
|
24 /** |
|
25 * Parser for preprocessor definitions and include statements |
|
26 * |
|
27 */ |
|
28 class PreprocessorDefinitionParser { |
|
29 |
|
30 /** |
|
31 * Source parser |
|
32 */ |
|
33 private SourceParser parser; |
|
34 |
|
35 /** |
|
36 * List of #define's found from source |
|
37 */ |
|
38 protected ArrayList<SourcePreprocessorDefinition> preprocessorDefinitions; |
|
39 |
|
40 /** |
|
41 * List of #include's found from source |
|
42 */ |
|
43 protected ArrayList<SourceInclude> includes; |
|
44 |
|
45 /** |
|
46 * Constructor |
|
47 * |
|
48 * @param parser |
|
49 * the source parser |
|
50 */ |
|
51 PreprocessorDefinitionParser(SourceParser parser) { |
|
52 this.parser = parser; |
|
53 } |
|
54 |
|
55 /** |
|
56 * Resets all definitions parsed from the source |
|
57 */ |
|
58 void reset() { |
|
59 if (preprocessorDefinitions != null) { |
|
60 preprocessorDefinitions.clear(); |
|
61 } |
|
62 if (includes != null) { |
|
63 includes.clear(); |
|
64 } |
|
65 } |
|
66 |
|
67 /** |
|
68 * Locates the value of a preprocessor definition for given name. |
|
69 * |
|
70 * @param name |
|
71 * the name of the definition |
|
72 * @return the value or null if not found |
|
73 * @throws SourceParserException |
|
74 * if parser fails |
|
75 */ |
|
76 String findDefine(String name) throws SourceParserException { |
|
77 if (preprocessorDefinitions == null |
|
78 || preprocessorDefinitions.isEmpty()) { |
|
79 createDefines(); |
|
80 } |
|
81 Iterator<SourcePreprocessorDefinition> itr = preprocessorDefinitions |
|
82 .iterator(); |
|
83 String retval = null; |
|
84 while (itr.hasNext() && retval == null) { |
|
85 SourcePreprocessorDefinition def = itr.next(); |
|
86 if (def.getName().equals(name)) { |
|
87 retval = def.getValue(); |
|
88 } |
|
89 } |
|
90 return retval; |
|
91 } |
|
92 |
|
93 /** |
|
94 * Finds an include definition with given name |
|
95 * |
|
96 * @param name |
|
97 * the include file name |
|
98 * @return |
|
99 * <ul> |
|
100 * <li>if found, index to start of #include |
|
101 * <li>if not, -1 - index to end of last #include |
|
102 * </ul> |
|
103 * @throws SourceParserException |
|
104 * if parser fails |
|
105 */ |
|
106 int findInclude(String name) throws SourceParserException { |
|
107 |
|
108 createIncludes(); |
|
109 |
|
110 Iterator<SourceInclude> itr = includes.iterator(); |
|
111 int ret = -1; |
|
112 while (itr.hasNext()) { |
|
113 SourceInclude inc = itr.next(); |
|
114 if (inc.getHeaderName().equalsIgnoreCase(name)) { |
|
115 ret = inc.getOffset(); |
|
116 } |
|
117 } |
|
118 if (ret == -1 && includes.size() > 0) { |
|
119 SourceInclude inc = includes.get(includes.size() - 1); |
|
120 ret = -1 - (inc.getOffset() + inc.getLength()); |
|
121 } |
|
122 return ret; |
|
123 } |
|
124 |
|
125 /** |
|
126 * Creates the list of preprocessor definitions. This only works with simple |
|
127 * values |
|
128 * |
|
129 * @throws SourceParserException |
|
130 * if parser fails |
|
131 */ |
|
132 private void createDefines() throws SourceParserException { |
|
133 if (preprocessorDefinitions == null) { |
|
134 preprocessorDefinitions = new ArrayList<SourcePreprocessorDefinition>(); |
|
135 } else { |
|
136 preprocessorDefinitions.clear(); |
|
137 } |
|
138 Iterator<SourceExcludedArea> excludedAreas = parser.getExcludedAreas() |
|
139 .iterator(); |
|
140 while (excludedAreas.hasNext()) { |
|
141 createDefineFromExcludedArea(excludedAreas.next()); |
|
142 } |
|
143 } |
|
144 |
|
145 /** |
|
146 * Creates the list of include definitions |
|
147 * |
|
148 * @throws SourceParserException |
|
149 * if parser fails |
|
150 */ |
|
151 private void createIncludes() throws SourceParserException { |
|
152 if (includes == null) { |
|
153 includes = new ArrayList<SourceInclude>(); |
|
154 } else { |
|
155 includes.clear(); |
|
156 } |
|
157 Iterator<SourceExcludedArea> excludedAreas = parser.getExcludedAreas() |
|
158 .iterator(); |
|
159 while (excludedAreas.hasNext()) { |
|
160 createIncludeFromExcludedArea(excludedAreas.next()); |
|
161 } |
|
162 } |
|
163 |
|
164 /** |
|
165 * Creates an #define definition from given excluded area |
|
166 * |
|
167 * @param area |
|
168 * the area |
|
169 * @throws SourceParserException |
|
170 */ |
|
171 private void createDefineFromExcludedArea(SourceExcludedArea area) |
|
172 throws SourceParserException { |
|
173 if (area.getType() == SourceExcludedArea.PREPROCESSOR_DEFINITION |
|
174 && area.getLength() > SourceConstants.DEFINE.length()) { |
|
175 String tag = parser.getSource().get(area.getOffset(), |
|
176 SourceConstants.DEFINE.length()); |
|
177 if (tag.equals(SourceConstants.DEFINE)) { |
|
178 // Cannot use SKIP_ALL here, since it contains SKIP_PREPROCESSOR |
|
179 SourceIterator itr = parser.createIterator(area.getOffset() |
|
180 + SourceConstants.DEFINE.length(), |
|
181 SourceParser.SKIP_WHITE_SPACES |
|
182 | SourceParser.SKIP_COMMENTS); |
|
183 if (itr.hasNext()) { |
|
184 parsePreprocessorDefinition(itr); |
|
185 } |
|
186 } |
|
187 } |
|
188 } |
|
189 |
|
190 /** |
|
191 * Creates an #include definition from given excluded area |
|
192 * |
|
193 * @param area |
|
194 * the area |
|
195 * @throws SourceParserException |
|
196 * if parser fails |
|
197 */ |
|
198 private void createIncludeFromExcludedArea(SourceExcludedArea area) |
|
199 throws SourceParserException { |
|
200 if (area.getType() == SourceExcludedArea.PREPROCESSOR_DEFINITION |
|
201 && area.getLength() > SourceConstants.INCLUDE.length()) { |
|
202 String tag = parser.getSource().get(area.getOffset(), |
|
203 SourceConstants.INCLUDE.length()); |
|
204 if (tag.equals(SourceConstants.INCLUDE)) { |
|
205 // Cannot use SKIP_ALL here, since it contains SKIP_PREPROCESSOR |
|
206 SourceIterator itr = parser.createIterator(area.getOffset() |
|
207 + SourceConstants.INCLUDE.length(), |
|
208 SourceParser.SKIP_WHITE_SPACES |
|
209 | SourceParser.SKIP_COMMENTS); |
|
210 if (itr.hasNext()) { |
|
211 parseInclude(itr); |
|
212 } |
|
213 } |
|
214 } |
|
215 } |
|
216 |
|
217 /** |
|
218 * Parses a preprocessor definition. This only finds simple values |
|
219 * |
|
220 * @param itr |
|
221 * source iterator, positioned so that next will return the first |
|
222 * character of the name of the definition |
|
223 * @throws SourceParserException |
|
224 * if parser fails |
|
225 */ |
|
226 private void parsePreprocessorDefinition(SourceIterator itr) |
|
227 throws SourceParserException { |
|
228 int start = itr.nextIndex(); |
|
229 int defstart = -1; |
|
230 SourcePreprocessorDefinition def = new SourcePreprocessorDefinition( |
|
231 parser, start); |
|
232 while (itr.hasNext() && def != null) { |
|
233 itr.next(); |
|
234 if (itr.hasSkipped()) { |
|
235 if (defstart == -1) { |
|
236 if ((itr.previousIndex() + 1) > start) { |
|
237 def.setName(parser.getSource().get(start, |
|
238 itr.previousIndex() + 1 - start)); |
|
239 defstart = itr.currentIndex(); |
|
240 } else { |
|
241 def = null; |
|
242 } |
|
243 } else { |
|
244 def.setValue(parser.getSource().get(defstart, |
|
245 itr.previousIndex() + 1 - defstart)); |
|
246 def.setLength(itr.previousIndex() + 1 - def.getOffset()); |
|
247 preprocessorDefinitions.add(def); |
|
248 def = null; |
|
249 } |
|
250 } |
|
251 } |
|
252 } |
|
253 |
|
254 /** |
|
255 * Parses an include line |
|
256 * |
|
257 * @param itr |
|
258 * source iterator, positioned so that next will return the first |
|
259 * character of the name of the definition |
|
260 * @throws SourceParserException |
|
261 * if parser fails |
|
262 */ |
|
263 private void parseInclude(SourceIterator itr) throws SourceParserException { |
|
264 int start = itr.nextIndex(); |
|
265 SourceInclude inc = new SourceInclude(parser, start); |
|
266 while (itr.hasNext() && inc != null) { |
|
267 itr.next(); |
|
268 if (itr.hasSkipped() && (itr.previousIndex()) > (start + 1)) { |
|
269 inc.setHeaderName(parser.getSource().get(start + 1, |
|
270 itr.previousIndex() - (start + 1))); |
|
271 inc.setLength(itr.previousIndex() - inc.getOffset() + 1); |
|
272 includes.add(inc); |
|
273 inc = null; |
|
274 } |
|
275 } |
|
276 } |
|
277 |
|
278 } |