/* * This file is part of the API Extractor project. * * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * Copyright 2005 Roberto Raggi * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef PP_ENGINE_BITS_H #define PP_ENGINE_BITS_H #include "pp.h" #include #include #include namespace rpp { inline std::string pp::fix_file_path(std::string const &filename) const { #if defined (PP_OS_WIN) std::string s = filename; for (std::string::iterator it = s.begin(); it != s.end(); ++it) { if (*it == '/') *it = '\\'; } return s; #else return filename; #endif } inline bool pp::is_absolute(std::string const &filename) const { #if defined(PP_OS_WIN) return filename.length() >= 3 && filename.at(1) == ':' && (filename.at(2) == '\\' || filename.at(2) == '/'); #else return filename.length() >= 1 && filename.at(0) == '/'; #endif } template void pp::file(std::string const &filename, _OutputIterator __result) { FILE *fp = std::fopen(filename.c_str(), "rb"); if (fp != 0) { std::string was = env.current_file; env.current_file = filename; file(fp, __result); env.current_file = was; } //else //std::cerr << "** WARNING file ``" << filename << " not found!" << std::endl; } template void pp::file(FILE *fp, _OutputIterator __result) { assert(fp != 0); #if defined (HAVE_MMAP) struct stat st; fstat(FILENO(fp), &st); std::size_t size = st.st_size; char *buffer = 0; buffer = (char *) ::mmap(0, size, PROT_READ, MAP_SHARED, FILENO(fp), 0); fclose(fp); if (!buffer || buffer == (char*) - 1) return; this->operator()(buffer, buffer + size, __result); ::munmap(buffer, size); #else std::string buffer; while (!feof(fp)) { char tmp[1024]; int read = (int) fread(tmp, sizeof(char), 1023, fp); tmp[read] = '\0'; buffer += tmp; } fclose(fp); this->operator()(buffer.c_str(), buffer.c_str() + buffer.size(), __result); #endif } template bool pp::find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot) { int was = env.current_line; while (__first != __last) { if (pp_isspace(*__first)) { if (*__first == '\n') ++env.current_line; ++__first; } else if (_PP_internal::comment_p(__first, __last)) { __first = skip_comment_or_divop(__first, __last); env.current_line += skip_comment_or_divop.lines; } else if (*__first == '#') { __first = skip_blanks(++__first, __last); env.current_line += skip_blanks.lines; if (__first != __last && *__first == 'i') { _InputIterator __begin = __first; __first = skip_identifier(__begin, __last); env.current_line += skip_identifier.lines; std::string __directive(__begin, __first); if (__directive == "ifndef") { __first = skip_blanks(__first, __last); env.current_line += skip_blanks.lines; __begin = __first; __first = skip_identifier(__first, __last); env.current_line += skip_identifier.lines; if (__begin != __first && __first != __last) { __prot->assign(__begin, __first); return true; } } } break; } else break; } env.current_line = was; return false; } inline pp::PP_DIRECTIVE_TYPE pp::find_directive(char const *__directive, std::size_t __size) const { switch (__size) { case 2: if (__directive[0] == 'i' && __directive[1] == 'f') return PP_IF; break; case 4: if (__directive[0] == 'e' && !strcmp(__directive, "elif")) return PP_ELIF; else if (__directive[0] == 'e' && !strcmp(__directive, "else")) return PP_ELSE; break; case 5: if (__directive[0] == 'i' && !strcmp(__directive, "ifdef")) return PP_IFDEF; else if (__directive[0] == 'u' && !strcmp(__directive, "undef")) return PP_UNDEF; else if (__directive[0] == 'e') { if (!strcmp(__directive, "endif")) return PP_ENDIF; else if (!strcmp(__directive, "error")) return PP_ERROR; } break; case 6: if (__directive[0] == 'i' && !strcmp(__directive, "ifndef")) return PP_IFNDEF; else if (__directive[0] == 'd' && !strcmp(__directive, "define")) return PP_DEFINE; else if (__directive[0] == 'p' && !strcmp(__directive, "pragma")) return PP_PRAGMA; break; case 7: if (__directive[0] == 'i' && !strcmp(__directive, "include")) return PP_INCLUDE; else if (!strcmp(__directive, "warning")) return PP_WARNING; break; case 12: if (__directive[0] == 'i' && !strcmp(__directive, "include_next")) return PP_INCLUDE_NEXT; break; default: break; } std::cerr << "** WARNING unknown directive '#" << __directive << "' at " << env.current_file << ":" << env.current_line << std::endl; return PP_UNKNOWN_DIRECTIVE; } inline bool pp::file_isdir(std::string const &__filename) const { struct stat __st; #if defined(PP_OS_WIN) if (stat(__filename.c_str(), &__st) == 0) return (__st.st_mode & _S_IFDIR) == _S_IFDIR; else return false; #else if (lstat(__filename.c_str(), &__st) == 0) return (__st.st_mode & S_IFDIR) == S_IFDIR; else return false; #endif } inline bool pp::file_exists(std::string const &__filename) const { struct stat __st; #if defined(PP_OS_WIN) return stat(__filename.c_str(), &__st) == 0; #else return lstat(__filename.c_str(), &__st) == 0; #endif } inline FILE *pp::find_include_file(std::string const &__input_filename, std::string *__filepath, INCLUDE_POLICY __include_policy, bool __skip_current_path) const { assert(__filepath != 0); assert(! __input_filename.empty()); __filepath->assign(__input_filename); if (is_absolute(*__filepath)) return std::fopen(__filepath->c_str(), "r"); if (! env.current_file.empty()) _PP_internal::extract_file_path(env.current_file, __filepath); if (__include_policy == INCLUDE_LOCAL && ! __skip_current_path) { std::string __tmp(*__filepath); __tmp += __input_filename; if (file_exists(__tmp) && !file_isdir(__tmp)) { __filepath->append(__input_filename); return std::fopen(__filepath->c_str(), "r"); } } std::vector::const_iterator it = include_paths.begin(); if (__skip_current_path) { it = std::find(include_paths.begin(), include_paths.end(), *__filepath); if (it != include_paths.end()) ++it; else it = include_paths.begin(); } for (; it != include_paths.end(); ++it) { if (__skip_current_path && it == include_paths.begin()) continue; __filepath->assign(*it); __filepath->append(__input_filename); if (file_exists(*__filepath) && !file_isdir(*__filepath)) return std::fopen(__filepath->c_str(), "r"); #ifdef Q_OS_MAC // try in Framework path on Mac, if there is a path in front // ### what about escaped slashes? size_t slashPos = __input_filename.find('/'); if (slashPos != std::string::npos) { __filepath->assign(*it); __filepath->append(__input_filename.substr(0, slashPos)); __filepath->append(".framework/Headers/"); __filepath->append(__input_filename.substr(slashPos + 1, std::string::npos)); std::cerr << *__filepath << "\n"; if (file_exists(*__filepath) && !file_isdir(*__filepath)) return fopen(__filepath->c_str(), "r"); } #endif // Q_OS_MAC } return 0; } template _InputIterator pp::handle_directive(char const *__directive, std::size_t __size, _InputIterator __first, _InputIterator __last, _OutputIterator __result) { __first = skip_blanks(__first, __last); PP_DIRECTIVE_TYPE d = find_directive(__directive, __size); switch (d) { case PP_DEFINE: if (! skipping()) return handle_define(__first, __last); break; case PP_INCLUDE: case PP_INCLUDE_NEXT: if (! skipping()) return handle_include(d == PP_INCLUDE_NEXT, __first, __last, __result); break; case PP_UNDEF: if (! skipping()) return handle_undef(__first, __last); break; case PP_ELIF: return handle_elif(__first, __last); case PP_ELSE: return handle_else(__first, __last); case PP_ENDIF: return handle_endif(__first, __last); case PP_IF: return handle_if(__first, __last); case PP_IFDEF: return handle_ifdef(false, __first, __last); case PP_IFNDEF: return handle_ifdef(true, __first, __last); default: break; } return __first; } template _InputIterator pp::handle_include(bool __skip_current_path, _InputIterator __first, _InputIterator __last, _OutputIterator __result) { if (pp_isalpha(*__first) || *__first == '_') { pp_macro_expander expand_include(env); std::string name; name.reserve(255); expand_include(__first, __last, std::back_inserter(name)); std::string::iterator it = skip_blanks(name.begin(), name.end()); assert(it != name.end() && (*it == '<' || *it == '"')); handle_include(__skip_current_path, it, name.end(), __result); return __first; } assert(*__first == '<' || *__first == '"'); int quote = (*__first == '"') ? '"' : '>'; ++__first; _InputIterator end_name = __first; for (; end_name != __last; ++end_name) { assert(*end_name != '\n'); if (*end_name == quote) break; } std::string filename(__first, end_name); #ifdef PP_OS_WIN std::replace(filename.begin(), filename.end(), '/', '\\'); #endif std::string filepath; FILE *fp = find_include_file(filename, &filepath, quote == '>' ? INCLUDE_GLOBAL : INCLUDE_LOCAL, __skip_current_path); #if defined (PP_HOOK_ON_FILE_INCLUDED) PP_HOOK_ON_FILE_INCLUDED(env.current_file, fp ? filepath : filename, fp); #endif if (fp != 0) { std::string old_file = env.current_file; env.current_file = filepath; int __saved_lines = env.current_line; env.current_line = 1; //output_line (env.current_file, 1, __result); file(fp, __result); // restore the file name and the line position env.current_file = old_file; env.current_line = __saved_lines; // sync the buffer _PP_internal::output_line(env.current_file, env.current_line, __result); } #ifndef RPP_JAMBI // else // std::cerr << "*** WARNING " << filename << ": No such file or directory" << std::endl; #endif return __first; } template void pp::operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { #ifndef PP_NO_SMART_HEADER_PROTECTION std::string __prot; __prot.reserve(255); pp_fast_string __tmp(__prot.c_str(), __prot.size()); if (find_header_protection(__first, __last, &__prot) && env.resolve(&__tmp) != 0) { // std::cerr << "** DEBUG found header protection:" << __prot << std::endl; return; } #endif env.current_line = 1; char __buffer[512]; while (true) { __first = skip_blanks(__first, __last); env.current_line += skip_blanks.lines; if (__first == __last) break; else if (*__first == '#') { assert(*__first == '#'); __first = skip_blanks(++__first, __last); env.current_line += skip_blanks.lines; _InputIterator end_id = skip_identifier(__first, __last); env.current_line += skip_identifier.lines; std::size_t __size = end_id - __first; assert(__size < 512); char *__cp = __buffer; std::copy(__first, end_id, __cp); __cp[__size] = '\0'; end_id = skip_blanks(end_id, __last); __first = skip(end_id, __last); int was = env.current_line; (void) handle_directive(__buffer, __size, end_id, __first, __result); if (env.current_line != was) { env.current_line = was; _PP_internal::output_line(env.current_file, env.current_line, __result); } } else if (*__first == '\n') { // ### compress the line *__result++ = *__first++; ++env.current_line; } else if (skipping()) __first = skip(__first, __last); else { _PP_internal::output_line(env.current_file, env.current_line, __result); __first = expand(__first, __last, __result); env.current_line += expand.lines; if (expand.generated_lines) _PP_internal::output_line(env.current_file, env.current_line, __result); } } } inline pp::pp(pp_environment &__env): env(__env), expand(env) { iflevel = 0; _M_skipping[iflevel] = 0; _M_true_test[iflevel] = 0; } inline std::back_insert_iterator > pp::include_paths_inserter() { return std::back_inserter(include_paths); } inline std::vector::iterator pp::include_paths_begin() { return include_paths.begin(); } inline std::vector::iterator pp::include_paths_end() { return include_paths.end(); } inline std::vector::const_iterator pp::include_paths_begin() const { return include_paths.begin(); } inline std::vector::const_iterator pp::include_paths_end() const { return include_paths.end(); } inline void pp::push_include_path(std::string const &__path) { if (__path.empty() || __path [__path.size() - 1] != PATH_SEPARATOR) { std::string __tmp(__path); __tmp += PATH_SEPARATOR; include_paths.push_back(__tmp); } else include_paths.push_back(__path); } template _InputIterator pp::handle_define(_InputIterator __first, _InputIterator __last) { pp_macro macro; #if defined (PP_WITH_MACRO_POSITION) macro.file = pp_symbol::get(env.current_file); #endif std::string definition; __first = skip_blanks(__first, __last); _InputIterator end_macro_name = skip_identifier(__first, __last); pp_fast_string const *macro_name = pp_symbol::get(__first, end_macro_name); __first = end_macro_name; if (__first != __last && *__first == '(') { macro.function_like = true; macro.formals.reserve(5); __first = skip_blanks(++__first, __last); // skip '(' _InputIterator arg_end = skip_identifier(__first, __last); if (__first != arg_end) macro.formals.push_back(pp_symbol::get(__first, arg_end)); __first = skip_blanks(arg_end, __last); if (*__first == '.') { macro.variadics = true; while (*__first == '.') ++__first; } while (__first != __last && *__first == ',') { __first = skip_blanks(++__first, __last); arg_end = skip_identifier(__first, __last); if (__first != arg_end) macro.formals.push_back(pp_symbol::get(__first, arg_end)); __first = skip_blanks(arg_end, __last); if (*__first == '.') { macro.variadics = true; while (*__first == '.') ++__first; } } assert(*__first == ')'); ++__first; } __first = skip_blanks(__first, __last); while (__first != __last && *__first != '\n') { if (*__first == '/') { __first = skip_comment_or_divop(__first, __last); env.current_line += skip_comment_or_divop.lines; } if (*__first == '\\') { _InputIterator __begin = __first; __begin = skip_blanks(++__begin, __last); if (__begin != __last && *__begin == '\n') { ++macro.lines; __first = skip_blanks(++__begin, __last); definition += ' '; continue; } } definition += *__first++; } macro.definition = pp_symbol::get(definition); env.bind(macro_name, macro); return __first; } template _InputIterator pp::skip(_InputIterator __first, _InputIterator __last) { pp_skip_string_literal skip_string_literal; pp_skip_char_literal skip_char_literal; while (__first != __last && *__first != '\n') { if (*__first == '/') { __first = skip_comment_or_divop(__first, __last); env.current_line += skip_comment_or_divop.lines; } else if (*__first == '"') { __first = skip_string_literal(__first, __last); env.current_line += skip_string_literal.lines; } else if (*__first == '\'') { __first = skip_char_literal(__first, __last); env.current_line += skip_char_literal.lines; } else if (*__first == '\\') { __first = skip_blanks(++__first, __last); env.current_line += skip_blanks.lines; if (__first != __last && *__first == '\n') { ++__first; ++env.current_line; } } else ++__first; } return __first; } inline bool pp::test_if_level() { bool result = !_M_skipping[iflevel++]; _M_skipping[iflevel] = _M_skipping[iflevel - 1]; _M_true_test[iflevel] = false; return result; } inline int pp::skipping() const { return _M_skipping[iflevel]; } template _InputIterator pp::eval_primary(_InputIterator __first, _InputIterator __last, Value *result) { bool expect_paren = false; int token; __first = next_token(__first, __last, &token); switch (token) { case TOKEN_NUMBER: result->set_long(token_value); break; case TOKEN_UNUMBER: result->set_ulong(token_uvalue); break; case TOKEN_DEFINED: __first = next_token(__first, __last, &token); if (token == '(') { expect_paren = true; __first = next_token(__first, __last, &token); } if (token != TOKEN_IDENTIFIER) { std::cerr << "** WARNING expected ``identifier'' found:" << char(token) << std::endl; result->set_long(0); break; } result->set_long(env.resolve(token_text->c_str(), token_text->size()) != 0); next_token(__first, __last, &token); // skip '(' if (expect_paren) { _InputIterator next = next_token(__first, __last, &token); if (token != ')') std::cerr << "** WARNING expected ``)''" << std::endl; else __first = next; } break; case TOKEN_IDENTIFIER: result->set_long(0); break; case '-': __first = eval_primary(__first, __last, result); result->set_long(- result->l); return __first; case '+': __first = eval_primary(__first, __last, result); return __first; case '!': __first = eval_primary(__first, __last, result); result->set_long(result->is_zero()); return __first; case '(': __first = eval_constant_expression(__first, __last, result); next_token(__first, __last, &token); if (token != ')') std::cerr << "** WARNING expected ``)'' = " << token << std::endl; else __first = next_token(__first, __last, &token); break; default: result->set_long(0); } return __first; } template _InputIterator pp::eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_primary(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == '*' || token == '/' || token == '%') { Value value; __first = eval_primary(next, __last, &value); if (token == '*') result->op_mult(value); else if (token == '/') { if (value.is_zero()) { std::cerr << "** WARNING division by zero" << std::endl; result->set_long(0); } else result->op_div(value); } else { if (value.is_zero()) { std::cerr << "** WARNING division by zero" << std::endl; result->set_long(0); } else result->op_mod(value); } next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_additive(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_multiplicative(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == '+' || token == '-') { Value value; __first = eval_multiplicative(next, __last, &value); if (token == '+') result->op_add(value); else result->op_sub(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_shift(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_additive(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == TOKEN_LT_LT || token == TOKEN_GT_GT) { Value value; __first = eval_additive(next, __last, &value); if (token == TOKEN_LT_LT) result->op_lhs(value); else result->op_rhs(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_relational(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_shift(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == '<' || token == '>' || token == TOKEN_LT_EQ || token == TOKEN_GT_EQ) { Value value; __first = eval_shift(next, __last, &value); switch (token) { default: assert(0); break; case '<': result->op_lt(value); break; case '>': result->op_gt(value); break; case TOKEN_LT_EQ: result->op_le(value); break; case TOKEN_GT_EQ: result->op_ge(value); break; } next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_equality(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_relational(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == TOKEN_EQ_EQ || token == TOKEN_NOT_EQ) { Value value; __first = eval_relational(next, __last, &value); if (token == TOKEN_EQ_EQ) result->op_eq(value); else result->op_ne(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_and(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_equality(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == '&') { Value value; __first = eval_equality(next, __last, &value); result->op_bit_and(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_xor(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_and(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == '^') { Value value; __first = eval_and(next, __last, &value); result->op_bit_xor(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_or(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_xor(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == '|') { Value value; __first = eval_xor(next, __last, &value); result->op_bit_or(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_or(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == TOKEN_AND_AND) { Value value; __first = eval_or(next, __last, &value); result->op_and(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_logical_and(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); while (token == TOKEN_OR_OR) { Value value; __first = eval_logical_and(next, __last, &value); result->op_or(value); next = next_token(__first, __last, &token); } return __first; } template _InputIterator pp::eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result) { __first = eval_logical_or(__first, __last, result); int token; _InputIterator next = next_token(__first, __last, &token); if (token == '?') { Value left_value; __first = eval_constant_expression(next, __last, &left_value); __first = skip_blanks(__first, __last); __first = next_token(__first, __last, &token); if (token == ':') { Value right_value; __first = eval_constant_expression(__first, __last, &right_value); *result = !result->is_zero() ? left_value : right_value; } else { std::cerr << "** WARNING expected ``:'' = " << int (token) << std::endl; *result = left_value; } } return __first; } template _InputIterator pp::eval_expression(_InputIterator __first, _InputIterator __last, Value *result) { return __first = eval_constant_expression(skip_blanks(__first, __last), __last, result); } template _InputIterator pp::handle_if(_InputIterator __first, _InputIterator __last) { if (test_if_level()) { pp_macro_expander expand_condition(env); std::string condition; condition.reserve(255); expand_condition(skip_blanks(__first, __last), __last, std::back_inserter(condition)); Value result; result.set_long(0); eval_expression(condition.c_str(), condition.c_str() + condition.size(), &result); _M_true_test[iflevel] = !result.is_zero(); _M_skipping[iflevel] = result.is_zero(); } return __first; } template _InputIterator pp::handle_else(_InputIterator __first, _InputIterator /*__last*/) { if (iflevel == 0 && !skipping()) { std::cerr << "** WARNING #else without #if" << std::endl; } else if (iflevel > 0 && _M_skipping[iflevel - 1]) { _M_skipping[iflevel] = true; } else { _M_skipping[iflevel] = _M_true_test[iflevel]; } return __first; } template _InputIterator pp::handle_elif(_InputIterator __first, _InputIterator __last) { assert(iflevel > 0); if (iflevel == 0 && !skipping()) { std::cerr << "** WARNING #else without #if" << std::endl; } else if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1]) { Value result; __first = eval_expression(__first, __last, &result); _M_true_test[iflevel] = !result.is_zero(); _M_skipping[iflevel] = result.is_zero(); } else { _M_skipping[iflevel] = true; } return __first; } template _InputIterator pp::handle_endif(_InputIterator __first, _InputIterator /*__last*/) { if (iflevel == 0 && !skipping()) { std::cerr << "** WARNING #endif without #if" << std::endl; } else { _M_skipping[iflevel] = 0; _M_true_test[iflevel] = 0; --iflevel; } return __first; } template _InputIterator pp::handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last) { if (test_if_level()) { _InputIterator end_macro_name = skip_identifier(__first, __last); std::size_t __size; #if defined(__SUNPRO_CC) std::distance(__first, end_macro_name, __size); #else __size = std::distance(__first, end_macro_name); #endif assert(__size < 256); char __buffer [256]; std::copy(__first, end_macro_name, __buffer); bool value = env.resolve(__buffer, __size) != 0; __first = end_macro_name; if (check_undefined) value = !value; _M_true_test[iflevel] = value; _M_skipping[iflevel] = !value; } return __first; } template _InputIterator pp::handle_undef(_InputIterator __first, _InputIterator __last) { __first = skip_blanks(__first, __last); _InputIterator end_macro_name = skip_identifier(__first, __last); assert(end_macro_name != __first); std::size_t __size; #if defined(__SUNPRO_CC) std::distance(__first, end_macro_name, __size); #else __size = std::distance(__first, end_macro_name); #endif assert(__size < 256); char __buffer [256]; std::copy(__first, end_macro_name, __buffer); pp_fast_string const __tmp(__buffer, __size); env.unbind(&__tmp); __first = end_macro_name; return __first; } template char pp::peek_char(_InputIterator __first, _InputIterator __last) { if (__first == __last) return 0; return *++__first; } template _InputIterator pp::next_token(_InputIterator __first, _InputIterator __last, int *kind) { __first = skip_blanks(__first, __last); if (__first == __last) { *kind = 0; return __first; } char ch = *__first; char ch2 = peek_char(__first, __last); switch (ch) { case '/': if (ch2 == '/' || ch2 == '*') { __first = skip_comment_or_divop(__first, __last); return next_token(__first, __last, kind); } ++__first; *kind = '/'; break; case '<': ++__first; if (ch2 == '<') { ++__first; *kind = TOKEN_LT_LT; } else if (ch2 == '=') { ++__first; *kind = TOKEN_LT_EQ; } else *kind = '<'; return __first; case '>': ++__first; if (ch2 == '>') { ++__first; *kind = TOKEN_GT_GT; } else if (ch2 == '=') { ++__first; *kind = TOKEN_GT_EQ; } else *kind = '>'; return __first; case '!': ++__first; if (ch2 == '=') { ++__first; *kind = TOKEN_NOT_EQ; } else *kind = '!'; return __first; case '=': ++__first; if (ch2 == '=') { ++__first; *kind = TOKEN_EQ_EQ; } else *kind = '='; return __first; case '|': ++__first; if (ch2 == '|') { ++__first; *kind = TOKEN_OR_OR; } else *kind = '|'; return __first; case '&': ++__first; if (ch2 == '&') { ++__first; *kind = TOKEN_AND_AND; } else *kind = '&'; return __first; default: if (pp_isalpha(ch) || ch == '_') { _InputIterator end = skip_identifier(__first, __last); _M_current_text.assign(__first, end); token_text = &_M_current_text; __first = end; if (*token_text == "defined") *kind = TOKEN_DEFINED; else *kind = TOKEN_IDENTIFIER; } else if (pp_isdigit(ch)) { _InputIterator end = skip_number(__first, __last); std::string __str(__first, __last); char ch = __str [__str.size() - 1]; if (ch == 'u' || ch == 'U') { token_uvalue = strtoul(__str.c_str(), 0, 0); *kind = TOKEN_UNUMBER; } else { token_value = strtol(__str.c_str(), 0, 0); *kind = TOKEN_NUMBER; } __first = end; } else *kind = *__first++; } return __first; } } // namespace rpp #endif // PP_ENGINE_BITS_H // kate: space-indent on; indent-width 2; replace-tabs on;