Mercurial > projects > qtd
annotate generator/parser/rpp/pp-engine-bits.h @ 382:1d56b2a2e10c
Fixes to debugging stuff. Added size_t as primitive type to workaround Qwt build failure in debug
author | Max Samukha <maxter@spambox.com> |
---|---|
date | Mon, 12 Jul 2010 20:36:07 +0300 |
parents | 09a0f1d048f2 |
children |
rev | line source |
---|---|
1 | 1 /**************************************************************************** |
2 ** | |
52
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
3 ** Copyright (C) 1992-2009 Nokia. All rights reserved. |
1 | 4 ** Copyright 2005 Roberto Raggi <roberto@kdevelop.org> |
5 ** | |
6 ** This file is part of Qt Jambi. | |
7 ** | |
52
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
8 ** Commercial Usage |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
9 Licensees holding valid Qt Commercial licenses may use this file in |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
10 accordance with the Qt Commercial License Agreement provided with the |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
11 Software or, alternatively, in accordance with the terms contained in |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
12 a written agreement between you and Nokia. |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
13 |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
14 GNU Lesser General Public License Usage |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
15 Alternatively, this file may be used under the terms of the GNU Lesser |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
16 General Public License version 2.1 as published by the Free Software |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
17 Foundation and appearing in the file LICENSE.LGPL included in the |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
18 packaging of this file. Please review the following information to |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
19 ensure the GNU Lesser General Public License version 2.1 requirements |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
20 will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
21 |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
22 In addition, as a special exception, Nokia gives you certain |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
23 additional rights. These rights are described in the Nokia Qt LGPL |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
24 Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
25 package. |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
26 |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
27 GNU General Public License Usage |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
28 Alternatively, this file may be used under the terms of the GNU |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
29 General Public License version 3.0 as published by the Free Software |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
30 Foundation and appearing in the file LICENSE.GPL included in the |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
31 packaging of this file. Please review the following information to |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
32 ensure the GNU General Public License version 3.0 requirements will be |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
33 met: http://www.gnu.org/copyleft/gpl.html. |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
34 |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
35 If you are unsure which license is appropriate for your use, please |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
36 contact the sales department at qt-sales@nokia.com. |
1 | 37 |
38 ** | |
39 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | |
40 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
41 ** | |
42 ****************************************************************************/ | |
43 | |
44 #ifndef PP_ENGINE_BITS_H | |
45 #define PP_ENGINE_BITS_H | |
46 | |
52
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
47 #include <cstdio> |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
48 |
1 | 49 namespace rpp { |
50 | |
51 inline std::string pp::fix_file_path(std::string const &filename) const | |
52 { | |
53 #if defined (PP_OS_WIN) | |
54 std::string s = filename; | |
55 for (std::string::iterator it = s.begin(); it != s.end(); ++it) | |
56 { | |
57 if (*it == '/') | |
58 *it = '\\'; | |
59 } | |
60 return s; | |
61 #else | |
62 return filename; | |
63 #endif | |
64 } | |
65 | |
66 inline bool pp::is_absolute(std::string const &filename) const | |
67 { | |
68 #if defined(PP_OS_WIN) | |
69 return filename.length() >= 3 | |
70 && filename.at(1) == ':' | |
71 && (filename.at(2) == '\\' || filename.at(2) == '/'); | |
72 #else | |
73 return filename.length() >= 1 | |
74 && filename.at(0) == '/'; | |
75 #endif | |
76 } | |
77 | |
78 template <typename _OutputIterator> | |
79 void pp::file (std::string const &filename, _OutputIterator __result) | |
80 { | |
81 FILE *fp = fopen (filename.c_str(), "rb"); | |
82 if (fp != 0) | |
83 { | |
84 std::string was = env.current_file; | |
85 env.current_file = filename; | |
86 file (fp, __result); | |
87 env.current_file = was; | |
88 } | |
89 //else | |
90 //std::cerr << "** WARNING file ``" << filename << " not found!" << std::endl; | |
91 } | |
92 | |
93 template <typename _OutputIterator> | |
94 void pp::file (FILE *fp, _OutputIterator __result) | |
95 { | |
96 assert (fp != 0); | |
97 | |
98 #if defined (HAVE_MMAP) | |
99 struct stat st; | |
100 fstat(FILENO (fp), &st); | |
101 std::size_t size = st.st_size; | |
102 char *buffer = 0; | |
103 buffer = (char *) ::mmap(0, size, PROT_READ, MAP_SHARED, FILENO (fp), 0); | |
104 fclose (fp); | |
105 if (!buffer || buffer == (char*) -1) | |
106 return; | |
107 this->operator () (buffer, buffer + size, __result); | |
108 ::munmap(buffer, size); | |
109 #else | |
110 std::string buffer; | |
111 while (!feof(fp)) { | |
112 char tmp[1024]; | |
113 int read = (int) fread (tmp, sizeof(char), 1023, fp); | |
114 tmp[read] = '\0'; | |
115 buffer += tmp; | |
116 } | |
117 fclose (fp); | |
118 this->operator () (buffer.c_str(), buffer.c_str() + buffer.size(), __result); | |
119 #endif | |
120 } | |
121 | |
122 template <typename _InputIterator> | |
123 bool pp::find_header_protection (_InputIterator __first, _InputIterator __last, std::string *__prot) | |
124 { | |
125 int was = env.current_line; | |
126 | |
127 while (__first != __last) | |
128 { | |
129 if (pp_isspace (*__first)) | |
130 { | |
131 if (*__first == '\n') | |
132 ++env.current_line; | |
133 | |
134 ++__first; | |
135 } | |
136 else if (_PP_internal::comment_p (__first, __last)) | |
137 { | |
138 __first = skip_comment_or_divop (__first, __last); | |
139 env.current_line += skip_comment_or_divop.lines; | |
140 } | |
141 else if (*__first == '#') | |
142 { | |
143 __first = skip_blanks (++__first, __last); | |
144 env.current_line += skip_blanks.lines; | |
145 | |
146 if (__first != __last && *__first == 'i') | |
147 { | |
148 _InputIterator __begin = __first; | |
149 __first = skip_identifier (__begin, __last); | |
150 env.current_line += skip_identifier.lines; | |
151 | |
152 std::string __directive (__begin, __first); | |
153 | |
154 if (__directive == "ifndef") | |
155 { | |
156 __first = skip_blanks (__first, __last); | |
157 env.current_line += skip_blanks.lines; | |
158 | |
159 __begin = __first; | |
160 __first = skip_identifier (__first, __last); | |
161 env.current_line += skip_identifier.lines; | |
162 | |
163 if (__begin != __first && __first != __last) | |
164 { | |
165 __prot->assign (__begin, __first); | |
166 return true; | |
167 } | |
168 } | |
169 } | |
170 break; | |
171 } | |
172 else | |
173 break; | |
174 } | |
175 | |
176 env.current_line = was; | |
177 return false; | |
178 } | |
179 | |
180 inline pp::PP_DIRECTIVE_TYPE pp::find_directive (char const *__directive, std::size_t __size) const | |
181 { | |
182 switch (__size) | |
183 { | |
184 case 2: | |
185 if (__directive[0] == 'i' | |
186 && __directive[1] == 'f') | |
187 return PP_IF; | |
188 break; | |
189 | |
190 case 4: | |
191 if (__directive[0] == 'e' && !strcmp (__directive, "elif")) | |
192 return PP_ELIF; | |
193 else if (__directive[0] == 'e' && !strcmp (__directive, "else")) | |
194 return PP_ELSE; | |
195 break; | |
196 | |
197 case 5: | |
198 if (__directive[0] == 'i' && !strcmp (__directive, "ifdef")) | |
199 return PP_IFDEF; | |
200 else if (__directive[0] == 'u' && !strcmp (__directive, "undef")) | |
201 return PP_UNDEF; | |
202 else if (__directive[0] == 'e') { | |
203 if (!strcmp (__directive, "endif")) | |
204 return PP_ENDIF; | |
205 else if (!strcmp (__directive, "error")) | |
206 return PP_ERROR; | |
207 } | |
208 break; | |
209 | |
210 case 6: | |
211 if (__directive[0] == 'i' && !strcmp (__directive, "ifndef")) | |
212 return PP_IFNDEF; | |
213 else if (__directive[0] == 'd' && !strcmp (__directive, "define")) | |
214 return PP_DEFINE; | |
215 else if (__directive[0] == 'p' && !strcmp (__directive, "pragma")) | |
216 return PP_PRAGMA; | |
217 break; | |
218 | |
219 case 7: | |
220 if (__directive[0] == 'i' && !strcmp (__directive, "include")) | |
52
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
221 return PP_INCLUDE; |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
222 else if (__directive[0] == 'w' && !strcmp(__directive, "warning")) |
09a0f1d048f2
update parser to that from jambi 4.5, attemt to fix building with gcc 4.4
eldar
parents:
1
diff
changeset
|
223 return PP_WARNING; |
1 | 224 break; |
225 | |
226 case 12: | |
227 if (__directive[0] == 'i' && !strcmp (__directive, "include_next")) | |
228 return PP_INCLUDE_NEXT; | |
229 break; | |
230 | |
231 default: | |
232 break; | |
233 } | |
234 std::cerr << "** WARNING unknown directive '#" << __directive << "' at " << env.current_file << ":" << env.current_line << std::endl; | |
235 return PP_UNKNOWN_DIRECTIVE; | |
236 } | |
237 | |
238 inline bool pp::file_isdir (std::string const &__filename) const | |
239 { | |
240 struct stat __st; | |
241 #if defined(PP_OS_WIN) | |
242 if (stat(__filename.c_str (), &__st) == 0) | |
243 return (__st.st_mode & _S_IFDIR) == _S_IFDIR; | |
244 else | |
245 return false; | |
246 #else | |
247 if (lstat (__filename.c_str (), &__st) == 0) | |
248 return (__st.st_mode & S_IFDIR) == S_IFDIR; | |
249 else | |
250 return false; | |
251 #endif | |
252 } | |
253 | |
254 inline bool pp::file_exists (std::string const &__filename) const | |
255 { | |
256 struct stat __st; | |
257 #if defined(PP_OS_WIN) | |
258 return stat(__filename.c_str (), &__st) == 0; | |
259 #else | |
260 return lstat (__filename.c_str (), &__st) == 0; | |
261 #endif | |
262 } | |
263 | |
264 inline FILE *pp::find_include_file(std::string const &__input_filename, std::string *__filepath, | |
265 INCLUDE_POLICY __include_policy, bool __skip_current_path) const | |
266 { | |
267 assert (__filepath != 0); | |
268 assert (! __input_filename.empty()); | |
269 | |
270 __filepath->assign (__input_filename); | |
271 | |
272 if (is_absolute (*__filepath)) | |
273 return fopen (__filepath->c_str(), "r"); | |
274 | |
275 if (! env.current_file.empty ()) | |
276 _PP_internal::extract_file_path (env.current_file, __filepath); | |
277 | |
278 if (__include_policy == INCLUDE_LOCAL && ! __skip_current_path) | |
279 { | |
280 std::string __tmp (*__filepath); | |
281 __tmp += __input_filename; | |
282 | |
283 if (file_exists (__tmp) && !file_isdir(__tmp)) | |
284 { | |
285 __filepath->append (__input_filename); | |
286 return fopen (__filepath->c_str (), "r"); | |
287 } | |
288 } | |
289 | |
290 std::vector<std::string>::const_iterator it = include_paths.begin (); | |
291 | |
292 if (__skip_current_path) | |
293 { | |
294 it = std::find (include_paths.begin (), include_paths.end (), *__filepath); | |
295 | |
296 if (it != include_paths.end ()) | |
297 ++it; | |
298 | |
299 else | |
300 it = include_paths.begin (); | |
301 } | |
302 | |
303 for (; it != include_paths.end (); ++it) | |
304 { | |
305 if (__skip_current_path && it == include_paths.begin()) | |
306 continue; | |
307 | |
308 __filepath->assign (*it); | |
309 __filepath->append (__input_filename); | |
310 | |
311 if (file_exists (*__filepath) && !file_isdir(*__filepath)) | |
312 return fopen (__filepath->c_str(), "r"); | |
313 } | |
314 | |
315 return 0; | |
316 } | |
317 | |
318 template <typename _InputIterator, typename _OutputIterator> | |
319 _InputIterator pp::handle_directive(char const *__directive, std::size_t __size, | |
320 _InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
321 { | |
322 __first = skip_blanks (__first, __last); | |
323 | |
324 PP_DIRECTIVE_TYPE d = find_directive (__directive, __size); | |
325 switch (d) | |
326 { | |
327 case PP_DEFINE: | |
328 if (! skipping ()) | |
329 return handle_define (__first, __last); | |
330 break; | |
331 | |
332 case PP_INCLUDE: | |
333 case PP_INCLUDE_NEXT: | |
334 if (! skipping ()) | |
335 return handle_include (d == PP_INCLUDE_NEXT, __first, __last, __result); | |
336 break; | |
337 | |
338 case PP_UNDEF: | |
339 if (! skipping ()) | |
340 return handle_undef(__first, __last); | |
341 break; | |
342 | |
343 case PP_ELIF: | |
344 return handle_elif (__first, __last); | |
345 | |
346 case PP_ELSE: | |
347 return handle_else (__first, __last); | |
348 | |
349 case PP_ENDIF: | |
350 return handle_endif (__first, __last); | |
351 | |
352 case PP_IF: | |
353 return handle_if (__first, __last); | |
354 | |
355 case PP_IFDEF: | |
356 return handle_ifdef (false, __first, __last); | |
357 | |
358 case PP_IFNDEF: | |
359 return handle_ifdef (true, __first, __last); | |
360 | |
361 default: | |
362 break; | |
363 } | |
364 | |
365 return __first; | |
366 } | |
367 | |
368 template <typename _InputIterator, typename _OutputIterator> | |
369 _InputIterator pp::handle_include (bool __skip_current_path, _InputIterator __first, _InputIterator __last, | |
370 _OutputIterator __result) | |
371 { | |
372 if (pp_isalpha (*__first) || *__first == '_') | |
373 { | |
374 pp_macro_expander expand_include (env); | |
375 std::string name; | |
376 name.reserve (255); | |
377 expand_include (__first, __last, std::back_inserter (name)); | |
378 std::string::iterator it = skip_blanks (name.begin (), name.end ()); | |
379 assert (it != name.end () && (*it == '<' || *it == '"')); | |
380 handle_include (__skip_current_path, it, name.end (), __result); | |
381 return __first; | |
382 } | |
383 | |
384 assert (*__first == '<' || *__first == '"'); | |
385 int quote = (*__first == '"') ? '"' : '>'; | |
386 ++__first; | |
387 | |
388 _InputIterator end_name = __first; | |
389 for (; end_name != __last; ++end_name) | |
390 { | |
391 assert (*end_name != '\n'); | |
392 | |
393 if (*end_name == quote) | |
394 break; | |
395 } | |
396 | |
397 std::string filename (__first, end_name); | |
398 | |
399 #ifdef PP_OS_WIN | |
400 std::replace(filename.begin(), filename.end(), '/', '\\'); | |
401 #endif | |
402 | |
403 std::string filepath; | |
404 FILE *fp = find_include_file (filename, &filepath, quote == '>' ? INCLUDE_GLOBAL : INCLUDE_LOCAL, __skip_current_path); | |
405 | |
406 #if defined (PP_HOOK_ON_FILE_INCLUDED) | |
407 PP_HOOK_ON_FILE_INCLUDED (env.current_file, fp ? filepath : filename, fp); | |
408 #endif | |
409 | |
410 if (fp != 0) | |
411 { | |
412 std::string old_file = env.current_file; | |
413 env.current_file = filepath; | |
414 int __saved_lines = env.current_line; | |
415 | |
416 env.current_line = 1; | |
417 //output_line (env.current_file, 1, __result); | |
418 | |
419 file (fp, __result); | |
420 | |
421 // restore the file name and the line position | |
422 env.current_file = old_file; | |
423 env.current_line = __saved_lines; | |
424 | |
425 // sync the buffer | |
426 _PP_internal::output_line (env.current_file, env.current_line, __result); | |
427 } | |
428 #ifndef RPP_JAMBI | |
429 // else | |
430 // std::cerr << "*** WARNING " << filename << ": No such file or directory" << std::endl; | |
431 #endif | |
432 | |
433 return __first; | |
434 } | |
435 | |
436 template <typename _InputIterator, typename _OutputIterator> | |
437 void pp::operator () (_InputIterator __first, _InputIterator __last, _OutputIterator __result) | |
438 { | |
439 #ifndef PP_NO_SMART_HEADER_PROTECTION | |
440 std::string __prot; | |
441 __prot.reserve (255); | |
442 pp_fast_string __tmp (__prot.c_str (), __prot.size ()); | |
443 | |
444 if (find_header_protection (__first, __last, &__prot) | |
445 && env.resolve (&__tmp) != 0) | |
446 { | |
447 // std::cerr << "** DEBUG found header protection:" << __prot << std::endl; | |
448 return; | |
449 } | |
450 #endif | |
451 | |
452 env.current_line = 1; | |
453 char __buffer[512]; | |
454 | |
455 while (true) | |
456 { | |
457 __first = skip_blanks (__first, __last); | |
458 env.current_line += skip_blanks.lines; | |
459 | |
460 if (__first == __last) | |
461 break; | |
462 else if (*__first == '#') | |
463 { | |
464 assert (*__first == '#'); | |
465 __first = skip_blanks (++__first, __last); | |
466 env.current_line += skip_blanks.lines; | |
467 | |
468 _InputIterator end_id = skip_identifier (__first, __last); | |
469 env.current_line += skip_identifier.lines; | |
470 std::size_t __size = end_id - __first; | |
471 | |
472 assert (__size < 512); | |
473 char *__cp = __buffer; | |
474 std::copy (__first, end_id, __cp); | |
475 __cp[__size] = '\0'; | |
476 | |
477 end_id = skip_blanks (end_id, __last); | |
478 __first = skip (end_id, __last); | |
479 | |
480 int was = env.current_line; | |
481 (void) handle_directive (__buffer, __size, end_id, __first, __result); | |
482 | |
483 if (env.current_line != was) | |
484 { | |
485 env.current_line = was; | |
486 _PP_internal::output_line (env.current_file, env.current_line, __result); | |
487 } | |
488 } | |
489 else if (*__first == '\n') | |
490 { | |
491 // ### compress the line | |
492 *__result++ = *__first++; | |
493 ++env.current_line; | |
494 } | |
495 else if (skipping ()) | |
496 __first = skip (__first, __last); | |
497 else | |
498 { | |
499 _PP_internal::output_line (env.current_file, env.current_line, __result); | |
500 __first = expand (__first, __last, __result); | |
501 env.current_line += expand.lines; | |
502 | |
503 if (expand.generated_lines) | |
504 _PP_internal::output_line (env.current_file, env.current_line, __result); | |
505 } | |
506 } | |
507 } | |
508 | |
509 inline pp::pp (pp_environment &__env): | |
510 env (__env), expand (env) | |
511 { | |
512 iflevel = 0; | |
513 _M_skipping[iflevel] = 0; | |
514 _M_true_test[iflevel] = 0; | |
515 } | |
516 | |
517 inline std::back_insert_iterator<std::vector<std::string> > pp::include_paths_inserter () | |
518 { return std::back_inserter (include_paths); } | |
519 | |
520 inline std::vector<std::string>::iterator pp::include_paths_begin () | |
521 { return include_paths.begin (); } | |
522 | |
523 inline std::vector<std::string>::iterator pp::include_paths_end () | |
524 { return include_paths.end (); } | |
525 | |
526 inline std::vector<std::string>::const_iterator pp::include_paths_begin () const | |
527 { return include_paths.begin (); } | |
528 | |
529 inline std::vector<std::string>::const_iterator pp::include_paths_end () const | |
530 { return include_paths.end (); } | |
531 | |
532 inline void pp::push_include_path (std::string const &__path) | |
533 { | |
534 if (__path.empty () || __path [__path.size () - 1] != PATH_SEPARATOR) | |
535 { | |
536 std::string __tmp (__path); | |
537 __tmp += PATH_SEPARATOR; | |
538 include_paths.push_back (__tmp); | |
539 } | |
540 | |
541 else | |
542 include_paths.push_back (__path); | |
543 } | |
544 | |
545 template <typename _InputIterator> | |
546 _InputIterator pp::handle_define (_InputIterator __first, _InputIterator __last) | |
547 { | |
548 pp_macro macro; | |
549 #if defined (PP_WITH_MACRO_POSITION) | |
550 macro.file = pp_symbol::get (env.current_file); | |
551 #endif | |
552 std::string definition; | |
553 | |
554 __first = skip_blanks (__first, __last); | |
555 _InputIterator end_macro_name = skip_identifier (__first, __last); | |
556 pp_fast_string const *macro_name = pp_symbol::get (__first, end_macro_name); | |
557 __first = end_macro_name; | |
558 | |
559 if (__first != __last && *__first == '(') | |
560 { | |
561 macro.function_like = true; | |
562 macro.formals.reserve (5); | |
563 | |
564 __first = skip_blanks (++__first, __last); // skip '(' | |
565 _InputIterator arg_end = skip_identifier (__first, __last); | |
566 if (__first != arg_end) | |
567 macro.formals.push_back (pp_symbol::get (__first, arg_end)); | |
568 | |
569 __first = skip_blanks (arg_end, __last); | |
570 | |
571 if (*__first == '.') | |
572 { | |
573 macro.variadics = true; | |
574 while (*__first == '.') | |
575 ++__first; | |
576 } | |
577 | |
578 while (__first != __last && *__first == ',') | |
579 { | |
580 __first = skip_blanks (++__first, __last); | |
581 | |
582 arg_end = skip_identifier (__first, __last); | |
583 if (__first != arg_end) | |
584 macro.formals.push_back (pp_symbol::get (__first, arg_end)); | |
585 | |
586 __first = skip_blanks (arg_end, __last); | |
587 | |
588 if (*__first == '.') | |
589 { | |
590 macro.variadics = true; | |
591 while (*__first == '.') | |
592 ++__first; | |
593 } | |
594 } | |
595 | |
596 assert (*__first == ')'); | |
597 ++__first; | |
598 } | |
599 | |
600 __first = skip_blanks (__first, __last); | |
601 | |
602 while (__first != __last && *__first != '\n') | |
603 { | |
604 if (*__first == '/') { | |
605 __first = skip_comment_or_divop(__first, __last); | |
606 env.current_line += skip_comment_or_divop.lines; | |
607 } | |
608 | |
609 if (*__first == '\\') | |
610 { | |
611 _InputIterator __begin = __first; | |
612 __begin = skip_blanks (++__begin, __last); | |
613 | |
614 if (__begin != __last && *__begin == '\n') | |
615 { | |
616 ++macro.lines; | |
617 __first = skip_blanks (++__begin, __last); | |
618 definition += ' '; | |
619 continue; | |
620 } | |
621 } | |
622 | |
623 definition += *__first++; | |
624 } | |
625 | |
626 macro.definition = pp_symbol::get (definition); | |
627 env.bind (macro_name, macro); | |
628 | |
629 return __first; | |
630 } | |
631 | |
632 template <typename _InputIterator> | |
633 _InputIterator pp::skip (_InputIterator __first, _InputIterator __last) | |
634 { | |
635 pp_skip_string_literal skip_string_literal; | |
636 pp_skip_char_literal skip_char_literal; | |
637 | |
638 while (__first != __last && *__first != '\n') | |
639 { | |
640 if (*__first == '/') | |
641 { | |
642 __first = skip_comment_or_divop (__first, __last); | |
643 env.current_line += skip_comment_or_divop.lines; | |
644 } | |
645 else if (*__first == '"') | |
646 { | |
647 __first = skip_string_literal (__first, __last); | |
648 env.current_line += skip_string_literal.lines; | |
649 } | |
650 else if (*__first == '\'') | |
651 { | |
652 __first = skip_char_literal (__first, __last); | |
653 env.current_line += skip_char_literal.lines; | |
654 } | |
655 else if (*__first == '\\') | |
656 { | |
657 __first = skip_blanks (++__first, __last); | |
658 env.current_line += skip_blanks.lines; | |
659 | |
660 if (__first != __last && *__first == '\n') | |
661 { | |
662 ++__first; | |
663 ++env.current_line; | |
664 } | |
665 } | |
666 else | |
667 ++__first; | |
668 } | |
669 | |
670 return __first; | |
671 } | |
672 | |
673 inline bool pp::test_if_level() | |
674 { | |
675 bool result = !_M_skipping[iflevel++]; | |
676 _M_skipping[iflevel] = _M_skipping[iflevel - 1]; | |
677 _M_true_test[iflevel] = false; | |
678 return result; | |
679 } | |
680 | |
681 inline int pp::skipping() const | |
682 { return _M_skipping[iflevel]; } | |
683 | |
684 template <typename _InputIterator> | |
685 _InputIterator pp::eval_primary(_InputIterator __first, _InputIterator __last, Value *result) | |
686 { | |
687 bool expect_paren = false; | |
688 int token; | |
689 __first = next_token (__first, __last, &token); | |
690 | |
691 switch (token) | |
692 { | |
693 case TOKEN_NUMBER: | |
694 result->set_long (token_value); | |
695 break; | |
696 | |
697 case TOKEN_UNUMBER: | |
698 result->set_ulong (token_uvalue); | |
699 break; | |
700 | |
701 case TOKEN_DEFINED: | |
702 __first = next_token (__first, __last, &token); | |
703 | |
704 if (token == '(') | |
705 { | |
706 expect_paren = true; | |
707 __first = next_token (__first, __last, &token); | |
708 } | |
709 | |
710 if (token != TOKEN_IDENTIFIER) | |
711 { | |
712 std::cerr << "** WARNING expected ``identifier'' found:" << char(token) << std::endl; | |
713 result->set_long (0); | |
714 break; | |
715 } | |
716 | |
717 result->set_long (env.resolve (token_text->c_str (), token_text->size ()) != 0); | |
718 | |
719 next_token (__first, __last, &token); // skip '(' | |
720 | |
721 if (expect_paren) | |
722 { | |
723 _InputIterator next = next_token (__first, __last, &token); | |
724 if (token != ')') | |
725 std::cerr << "** WARNING expected ``)''" << std::endl; | |
726 else | |
727 __first = next; | |
728 } | |
729 break; | |
730 | |
731 case TOKEN_IDENTIFIER: | |
732 result->set_long (0); | |
733 break; | |
734 | |
735 case '-': | |
736 __first = eval_primary (__first, __last, result); | |
737 result->set_long (- result->l); | |
738 return __first; | |
739 | |
740 case '+': | |
741 __first = eval_primary (__first, __last, result); | |
742 return __first; | |
743 | |
744 case '!': | |
745 __first = eval_primary (__first, __last, result); | |
746 result->set_long (result->is_zero ()); | |
747 return __first; | |
748 | |
749 case '(': | |
750 __first = eval_constant_expression(__first, __last, result); | |
751 next_token (__first, __last, &token); | |
752 | |
753 if (token != ')') | |
754 std::cerr << "** WARNING expected ``)'' = " << token << std::endl; | |
755 else | |
756 __first = next_token(__first, __last, &token); | |
757 break; | |
758 | |
759 default: | |
760 result->set_long (0); | |
761 } | |
762 | |
763 return __first; | |
764 } | |
765 | |
766 template <typename _InputIterator> | |
767 _InputIterator pp::eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result) | |
768 { | |
769 __first = eval_primary(__first, __last, result); | |
770 | |
771 int token; | |
772 _InputIterator next = next_token (__first, __last, &token); | |
773 | |
774 while (token == '*' || token == '/' || token == '%') | |
775 { | |
776 Value value; | |
777 __first = eval_primary(next, __last, &value); | |
778 | |
779 if (token == '*') | |
780 result->op_mult (value); | |
781 else if (token == '/') | |
782 { | |
783 if (value.is_zero ()) | |
784 { | |
785 std::cerr << "** WARNING division by zero" << std::endl; | |
786 result->set_long (0); | |
787 } | |
788 else | |
789 result->op_div (value); | |
790 } | |
791 else | |
792 { | |
793 if (value.is_zero ()) | |
794 { | |
795 std::cerr << "** WARNING division by zero" << std::endl; | |
796 result->set_long (0); | |
797 } | |
798 else | |
799 result->op_mod (value); | |
800 } | |
801 next = next_token (__first, __last, &token); | |
802 } | |
803 | |
804 return __first; | |
805 } | |
806 | |
807 template <typename _InputIterator> | |
808 _InputIterator pp::eval_additive(_InputIterator __first, _InputIterator __last, Value *result) | |
809 { | |
810 __first = eval_multiplicative(__first, __last, result); | |
811 | |
812 int token; | |
813 _InputIterator next = next_token (__first, __last, &token); | |
814 | |
815 while (token == '+' || token == '-') | |
816 { | |
817 Value value; | |
818 __first = eval_multiplicative(next, __last, &value); | |
819 | |
820 if (token == '+') | |
821 result->op_add (value); | |
822 else | |
823 result->op_sub (value); | |
824 next = next_token (__first, __last, &token); | |
825 } | |
826 | |
827 return __first; | |
828 } | |
829 | |
830 template <typename _InputIterator> | |
831 _InputIterator pp::eval_shift(_InputIterator __first, _InputIterator __last, Value *result) | |
832 { | |
833 __first = eval_additive(__first, __last, result); | |
834 | |
835 int token; | |
836 _InputIterator next = next_token (__first, __last, &token); | |
837 | |
838 while (token == TOKEN_LT_LT || token == TOKEN_GT_GT) | |
839 { | |
840 Value value; | |
841 __first = eval_additive (next, __last, &value); | |
842 | |
843 if (token == TOKEN_LT_LT) | |
844 result->op_lhs (value); | |
845 else | |
846 result->op_rhs (value); | |
847 next = next_token (__first, __last, &token); | |
848 } | |
849 | |
850 return __first; | |
851 } | |
852 | |
853 template <typename _InputIterator> | |
854 _InputIterator pp::eval_relational(_InputIterator __first, _InputIterator __last, Value *result) | |
855 { | |
856 __first = eval_shift(__first, __last, result); | |
857 | |
858 int token; | |
859 _InputIterator next = next_token (__first, __last, &token); | |
860 | |
861 while (token == '<' | |
862 || token == '>' | |
863 || token == TOKEN_LT_EQ | |
864 || token == TOKEN_GT_EQ) | |
865 { | |
866 Value value; | |
867 __first = eval_shift(next, __last, &value); | |
868 | |
869 switch (token) | |
870 { | |
871 default: | |
872 assert (0); | |
873 break; | |
874 | |
875 case '<': | |
876 result->op_lt (value); | |
877 break; | |
878 | |
879 case '>': | |
880 result->op_gt (value); | |
881 break; | |
882 | |
883 case TOKEN_LT_EQ: | |
884 result->op_le (value); | |
885 break; | |
886 | |
887 case TOKEN_GT_EQ: | |
888 result->op_ge (value); | |
889 break; | |
890 } | |
891 next = next_token (__first, __last, &token); | |
892 } | |
893 | |
894 return __first; | |
895 } | |
896 | |
897 template <typename _InputIterator> | |
898 _InputIterator pp::eval_equality(_InputIterator __first, _InputIterator __last, Value *result) | |
899 { | |
900 __first = eval_relational(__first, __last, result); | |
901 | |
902 int token; | |
903 _InputIterator next = next_token (__first, __last, &token); | |
904 | |
905 while (token == TOKEN_EQ_EQ || token == TOKEN_NOT_EQ) | |
906 { | |
907 Value value; | |
908 __first = eval_relational(next, __last, &value); | |
909 | |
910 if (token == TOKEN_EQ_EQ) | |
911 result->op_eq (value); | |
912 else | |
913 result->op_ne (value); | |
914 next = next_token (__first, __last, &token); | |
915 } | |
916 | |
917 return __first; | |
918 } | |
919 | |
920 template <typename _InputIterator> | |
921 _InputIterator pp::eval_and(_InputIterator __first, _InputIterator __last, Value *result) | |
922 { | |
923 __first = eval_equality(__first, __last, result); | |
924 | |
925 int token; | |
926 _InputIterator next = next_token (__first, __last, &token); | |
927 | |
928 while (token == '&') | |
929 { | |
930 Value value; | |
931 __first = eval_equality(next, __last, &value); | |
932 result->op_bit_and (value); | |
933 next = next_token (__first, __last, &token); | |
934 } | |
935 | |
936 return __first; | |
937 } | |
938 | |
939 template <typename _InputIterator> | |
940 _InputIterator pp::eval_xor(_InputIterator __first, _InputIterator __last, Value *result) | |
941 { | |
942 __first = eval_and(__first, __last, result); | |
943 | |
944 int token; | |
945 _InputIterator next = next_token (__first, __last, &token); | |
946 | |
947 while (token == '^') | |
948 { | |
949 Value value; | |
950 __first = eval_and(next, __last, &value); | |
951 result->op_bit_xor (value); | |
952 next = next_token (__first, __last, &token); | |
953 } | |
954 | |
955 return __first; | |
956 } | |
957 | |
958 template <typename _InputIterator> | |
959 _InputIterator pp::eval_or(_InputIterator __first, _InputIterator __last, Value *result) | |
960 { | |
961 __first = eval_xor(__first, __last, result); | |
962 | |
963 int token; | |
964 _InputIterator next = next_token (__first, __last, &token); | |
965 | |
966 while (token == '|') | |
967 { | |
968 Value value; | |
969 __first = eval_xor(next, __last, &value); | |
970 result->op_bit_or (value); | |
971 next = next_token (__first, __last, &token); | |
972 } | |
973 | |
974 return __first; | |
975 } | |
976 | |
977 template <typename _InputIterator> | |
978 _InputIterator pp::eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result) | |
979 { | |
980 __first = eval_or(__first, __last, result); | |
981 | |
982 int token; | |
983 _InputIterator next = next_token (__first, __last, &token); | |
984 | |
985 while (token == TOKEN_AND_AND) | |
986 { | |
987 Value value; | |
988 __first = eval_or(next, __last, &value); | |
989 result->op_and (value); | |
990 next = next_token (__first, __last, &token); | |
991 } | |
992 | |
993 return __first; | |
994 } | |
995 | |
996 template <typename _InputIterator> | |
997 _InputIterator pp::eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result) | |
998 { | |
999 __first = eval_logical_and (__first, __last, result); | |
1000 | |
1001 int token; | |
1002 _InputIterator next = next_token (__first, __last, &token); | |
1003 | |
1004 while (token == TOKEN_OR_OR) | |
1005 { | |
1006 Value value; | |
1007 __first = eval_logical_and(next, __last, &value); | |
1008 result->op_or (value); | |
1009 next = next_token (__first, __last, &token); | |
1010 } | |
1011 | |
1012 return __first; | |
1013 } | |
1014 | |
1015 template <typename _InputIterator> | |
1016 _InputIterator pp::eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result) | |
1017 { | |
1018 __first = eval_logical_or(__first, __last, result); | |
1019 | |
1020 int token; | |
1021 _InputIterator next = next_token (__first, __last, &token); | |
1022 | |
1023 if (token == '?') | |
1024 { | |
1025 Value left_value; | |
1026 __first = eval_constant_expression(next, __last, &left_value); | |
1027 __first = skip_blanks (__first, __last); | |
1028 | |
1029 __first = next_token(__first, __last, &token); | |
1030 if (token == ':') | |
1031 { | |
1032 Value right_value; | |
1033 __first = eval_constant_expression(__first, __last, &right_value); | |
1034 | |
1035 *result = !result->is_zero () ? left_value : right_value; | |
1036 } | |
1037 else | |
1038 { | |
1039 std::cerr << "** WARNING expected ``:'' = " << int (token) << std::endl; | |
1040 *result = left_value; | |
1041 } | |
1042 } | |
1043 | |
1044 return __first; | |
1045 } | |
1046 | |
1047 template <typename _InputIterator> | |
1048 _InputIterator pp::eval_expression (_InputIterator __first, _InputIterator __last, Value *result) | |
1049 { | |
1050 return __first = eval_constant_expression (skip_blanks (__first, __last), __last, result); | |
1051 } | |
1052 | |
1053 template <typename _InputIterator> | |
1054 _InputIterator pp::handle_if (_InputIterator __first, _InputIterator __last) | |
1055 { | |
1056 if (test_if_level()) | |
1057 { | |
1058 pp_macro_expander expand_condition (env); | |
1059 std::string condition; | |
1060 condition.reserve (255); | |
1061 expand_condition (skip_blanks (__first, __last), __last, std::back_inserter (condition)); | |
1062 | |
1063 Value result; | |
1064 result.set_long (0); | |
1065 eval_expression(condition.c_str (), condition.c_str () + condition.size (), &result); | |
1066 | |
1067 _M_true_test[iflevel] = !result.is_zero (); | |
1068 _M_skipping[iflevel] = result.is_zero (); | |
1069 } | |
1070 | |
1071 return __first; | |
1072 } | |
1073 | |
1074 template <typename _InputIterator> | |
1075 _InputIterator pp::handle_else (_InputIterator __first, _InputIterator /*__last*/) | |
1076 { | |
1077 if (iflevel == 0 && !skipping ()) | |
1078 { | |
1079 std::cerr << "** WARNING #else without #if" << std::endl; | |
1080 } | |
1081 else if (iflevel > 0 && _M_skipping[iflevel - 1]) | |
1082 { | |
1083 _M_skipping[iflevel] = true; | |
1084 } | |
1085 else | |
1086 { | |
1087 _M_skipping[iflevel] = _M_true_test[iflevel]; | |
1088 } | |
1089 | |
1090 return __first; | |
1091 } | |
1092 | |
1093 template <typename _InputIterator> | |
1094 _InputIterator pp::handle_elif (_InputIterator __first, _InputIterator __last) | |
1095 { | |
1096 assert(iflevel > 0); | |
1097 | |
1098 if (iflevel == 0 && !skipping()) | |
1099 { | |
1100 std::cerr << "** WARNING #else without #if" << std::endl; | |
1101 } | |
1102 else if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1]) | |
1103 { | |
1104 Value result; | |
1105 __first = eval_expression(__first, __last, &result); | |
1106 _M_true_test[iflevel] = !result.is_zero (); | |
1107 _M_skipping[iflevel] = result.is_zero (); | |
1108 } | |
1109 else | |
1110 { | |
1111 _M_skipping[iflevel] = true; | |
1112 } | |
1113 | |
1114 return __first; | |
1115 } | |
1116 | |
1117 template <typename _InputIterator> | |
1118 _InputIterator pp::handle_endif (_InputIterator __first, _InputIterator /*__last*/) | |
1119 { | |
1120 if (iflevel == 0 && !skipping()) | |
1121 { | |
1122 std::cerr << "** WARNING #endif without #if" << std::endl; | |
1123 } | |
1124 else | |
1125 { | |
1126 _M_skipping[iflevel] = 0; | |
1127 _M_true_test[iflevel] = 0; | |
1128 | |
1129 --iflevel; | |
1130 } | |
1131 | |
1132 return __first; | |
1133 } | |
1134 | |
1135 template <typename _InputIterator> | |
1136 _InputIterator pp::handle_ifdef (bool check_undefined, _InputIterator __first, _InputIterator __last) | |
1137 { | |
1138 if (test_if_level()) | |
1139 { | |
1140 _InputIterator end_macro_name = skip_identifier (__first, __last); | |
1141 | |
1142 std::size_t __size; | |
1143 #if defined(__SUNPRO_CC) | |
1144 std::distance (__first, end_macro_name, __size); | |
1145 #else | |
1146 __size = std::distance (__first, end_macro_name); | |
1147 #endif | |
1148 assert (__size < 256); | |
1149 | |
1150 char __buffer [256]; | |
1151 std::copy (__first, end_macro_name, __buffer); | |
1152 | |
1153 bool value = env.resolve (__buffer, __size) != 0; | |
1154 | |
1155 __first = end_macro_name; | |
1156 | |
1157 if (check_undefined) | |
1158 value = !value; | |
1159 | |
1160 _M_true_test[iflevel] = value; | |
1161 _M_skipping[iflevel] = !value; | |
1162 } | |
1163 | |
1164 return __first; | |
1165 } | |
1166 | |
1167 template <typename _InputIterator> | |
1168 _InputIterator pp::handle_undef(_InputIterator __first, _InputIterator __last) | |
1169 { | |
1170 __first = skip_blanks (__first, __last); | |
1171 _InputIterator end_macro_name = skip_identifier (__first, __last); | |
1172 assert (end_macro_name != __first); | |
1173 | |
1174 std::size_t __size; | |
1175 #if defined(__SUNPRO_CC) | |
1176 std::distance (__first, end_macro_name, __size); | |
1177 #else | |
1178 __size = std::distance (__first, end_macro_name); | |
1179 #endif | |
1180 | |
1181 assert (__size < 256); | |
1182 | |
1183 char __buffer [256]; | |
1184 std::copy (__first, end_macro_name, __buffer); | |
1185 | |
1186 pp_fast_string const __tmp (__buffer, __size); | |
1187 env.unbind (&__tmp); | |
1188 | |
1189 __first = end_macro_name; | |
1190 | |
1191 return __first; | |
1192 } | |
1193 | |
1194 template <typename _InputIterator> | |
1195 char pp::peek_char (_InputIterator __first, _InputIterator __last) | |
1196 { | |
1197 if (__first == __last) | |
1198 return 0; | |
1199 | |
1200 return *++__first; | |
1201 } | |
1202 | |
1203 template <typename _InputIterator> | |
1204 _InputIterator pp::next_token (_InputIterator __first, _InputIterator __last, int *kind) | |
1205 { | |
1206 __first = skip_blanks (__first, __last); | |
1207 | |
1208 if (__first == __last) | |
1209 { | |
1210 *kind = 0; | |
1211 return __first; | |
1212 } | |
1213 | |
1214 char ch = *__first; | |
1215 char ch2 = peek_char (__first, __last); | |
1216 | |
1217 switch (ch) | |
1218 { | |
1219 case '/': | |
1220 if (ch2 == '/' || ch2 == '*') | |
1221 { | |
1222 __first = skip_comment_or_divop (__first, __last); | |
1223 return next_token (__first, __last, kind); | |
1224 } | |
1225 ++__first; | |
1226 *kind = '/'; | |
1227 break; | |
1228 | |
1229 case '<': | |
1230 ++__first; | |
1231 if (ch2 == '<') | |
1232 { | |
1233 ++__first; | |
1234 *kind = TOKEN_LT_LT; | |
1235 } | |
1236 else if (ch2 == '=') | |
1237 { | |
1238 ++__first; | |
1239 *kind = TOKEN_LT_EQ; | |
1240 } | |
1241 else | |
1242 *kind = '<'; | |
1243 | |
1244 return __first; | |
1245 | |
1246 case '>': | |
1247 ++__first; | |
1248 if (ch2 == '>') | |
1249 { | |
1250 ++__first; | |
1251 *kind = TOKEN_GT_GT; | |
1252 } | |
1253 else if (ch2 == '=') | |
1254 { | |
1255 ++__first; | |
1256 *kind = TOKEN_GT_EQ; | |
1257 } | |
1258 else | |
1259 *kind = '>'; | |
1260 | |
1261 return __first; | |
1262 | |
1263 case '!': | |
1264 ++__first; | |
1265 if (ch2 == '=') | |
1266 { | |
1267 ++__first; | |
1268 *kind = TOKEN_NOT_EQ; | |
1269 } | |
1270 else | |
1271 *kind = '!'; | |
1272 | |
1273 return __first; | |
1274 | |
1275 case '=': | |
1276 ++__first; | |
1277 if (ch2 == '=') | |
1278 { | |
1279 ++__first; | |
1280 *kind = TOKEN_EQ_EQ; | |
1281 } | |
1282 else | |
1283 *kind = '='; | |
1284 | |
1285 return __first; | |
1286 | |
1287 case '|': | |
1288 ++__first; | |
1289 if (ch2 == '|') | |
1290 { | |
1291 ++__first; | |
1292 *kind = TOKEN_OR_OR; | |
1293 } | |
1294 else | |
1295 *kind = '|'; | |
1296 | |
1297 return __first; | |
1298 | |
1299 case '&': | |
1300 ++__first; | |
1301 if (ch2 == '&') | |
1302 { | |
1303 ++__first; | |
1304 *kind = TOKEN_AND_AND; | |
1305 } | |
1306 else | |
1307 *kind = '&'; | |
1308 | |
1309 return __first; | |
1310 | |
1311 default: | |
1312 if (pp_isalpha (ch) || ch == '_') | |
1313 { | |
1314 _InputIterator end = skip_identifier (__first, __last); | |
1315 _M_current_text.assign (__first, end); | |
1316 | |
1317 token_text = &_M_current_text; | |
1318 __first = end; | |
1319 | |
1320 if (*token_text == "defined") | |
1321 *kind = TOKEN_DEFINED; | |
1322 else | |
1323 *kind = TOKEN_IDENTIFIER; | |
1324 } | |
1325 else if (pp_isdigit (ch)) | |
1326 { | |
1327 _InputIterator end = skip_number (__first, __last); | |
1328 std::string __str (__first, __last); | |
1329 char ch = __str [__str.size () - 1]; | |
1330 if (ch == 'u' || ch == 'U') | |
1331 { | |
1332 token_uvalue = strtoul (__str.c_str (), 0, 0); | |
1333 *kind = TOKEN_UNUMBER; | |
1334 } | |
1335 else | |
1336 { | |
1337 token_value = strtol (__str.c_str (), 0, 0); | |
1338 *kind = TOKEN_NUMBER; | |
1339 } | |
1340 __first = end; | |
1341 } | |
1342 else | |
1343 *kind = *__first++; | |
1344 } | |
1345 | |
1346 return __first; | |
1347 } | |
1348 | |
1349 } // namespace rpp | |
1350 | |
1351 #endif // PP_ENGINE_BITS_H | |
1352 | |
1353 // kate: space-indent on; indent-width 2; replace-tabs on; |