diff options
author | Jörg Frings-Fürst <jff@merkur> | 2014-05-18 16:08:14 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <jff@merkur> | 2014-05-18 16:08:14 +0200 |
commit | a15cf65c44d5c224169c32ef5495b68c758134b7 (patch) | |
tree | 3419f58fc8e1b315ba8171910ee044c5d467c162 /libbackend-elements/backend-elements/indentation/sloc.hxx |
Imported Upstream version 3.3.0.2upstream/3.3.0.2
Diffstat (limited to 'libbackend-elements/backend-elements/indentation/sloc.hxx')
-rw-r--r-- | libbackend-elements/backend-elements/indentation/sloc.hxx | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/libbackend-elements/backend-elements/indentation/sloc.hxx b/libbackend-elements/backend-elements/indentation/sloc.hxx new file mode 100644 index 0000000..57e6989 --- /dev/null +++ b/libbackend-elements/backend-elements/indentation/sloc.hxx @@ -0,0 +1,277 @@ +// file : backend-elements/indentation/sloc.hxx +// author : Boris Kolpackov <boris@kolpackov.net> +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef BACKEND_ELEMENTS_INDENTATION_SLOC_HXX +#define BACKEND_ELEMENTS_INDENTATION_SLOC_HXX + +#include <backend-elements/types.hxx> +#include <backend-elements/indentation/buffer.hxx> + +#include <cctype> +#include <iostream> //@@ tmp + +namespace BackendElements +{ + namespace Indentation + { + template <typename C> + class SLOC: public Buffer<C>/*, public NonCopyable*/ + { + public: + typedef + typename Buffer<C>::Traits + Traits; + + typedef + typename Buffer<C>::AsChar + AsChar; + + typedef + typename Buffer<C>::AsInt + AsInt; + + typedef + typename Buffer<C>::Write + Write; + + public: + SLOC (Buffer<C>& out) + : out_ (out), + count_ (0), + prev_ ('\0'), + code_counted_ (false), + construct_ (Construct::code) + { + } + + UnsignedLong + count () const + { + return count_; + } + + public: + virtual AsInt + put (AsChar c) + { + typename Construct::Value old (construct_); + + switch (construct_) + { + case Construct::code: + { + code (c); + break; + } + case Construct::c_comment: + { + c_comment (c); + break; + } + case Construct::cxx_comment: + { + cxx_comment (c); + break; + } + case Construct::char_literal: + { + char_literal (c); + break; + } + case Construct::string_literal: + { + string_literal (c); + break; + } + } + + // There are cases when a previous character has been already + // 'used' and therefore can not be used again. Good example + // would be '/* *//'. Here, the second slash doesn't start + // C++ comment since it was already used by C comment. + // + // To account for this we are going to set prev_ to '\0' when + // the mode changes. + // + + prev_ = (old == construct_) ? c : '\0'; + + return out_.put (c); + } + + virtual Void + unbuffer () + { + } + + private: + Void + code (AsChar c) + { + bool count (true); + + switch (c) + { + case '/': + { + if (prev_ == '/') + { + construct_ = Construct::cxx_comment; + count = false; + } + else + { + // This slash can be a beginning of a comment but we + // yet have no way to know. Will have to examine it later + // (see below). + // + count = false; + } + + break; + } + case '*': + { + if (prev_ == '/') + { + construct_ = Construct::c_comment; + count = false; + } + break; + } + case '\'': + { + construct_ = Construct::char_literal; + break; + } + case '"': + { + construct_ = Construct::string_literal; + break; + } + case '\n': + { + code_counted_ = false; // reset for a new line + count = false; + break; + } + default: + { + if (std::isspace (c)) + count = false; + break; + } + } + + // The second condition here accounts for the fact that we cannot + // count '/' right away since it can be a beginning of a comment. + // + if (!code_counted_ && + (count || (prev_ == '/' && construct_ == Construct::code))) + { + //std::wcerr << "detected code @ " << c << std::endl; + count_++; + code_counted_ = true; + } + } + + Void + c_comment (AsChar c) + { + switch (c) + { + case '/': + { + if (prev_ == '*') + construct_ = Construct::code; + break; + } + case '\n': + { + code_counted_ = false; // reset for a new line + break; + } + } + } + + Void + cxx_comment (AsChar c) + { + switch (c) + { + case '\n': + { + construct_ = Construct::code; + code_counted_ = false; // reset for a new line + break; + } + } + } + + Void + char_literal (AsChar c) + { + switch (c) + { + case '\'': + { + if (prev_ != '\\') + construct_ = Construct::code; + break; + } + } + } + + Void + string_literal (AsChar c) + { + switch (c) + { + case '"': + { + if (prev_ != '\\') + construct_ = Construct::code; + break; + } + case '\n': + { + /*@@ Should I count multi-line string literal as multiple SLOC? */ + break; + } + } + } + + private: + Buffer<C>& out_; + UnsignedLong count_; + + AsChar prev_; // previous character or '\0' + + struct Construct + { + enum Value + { + code, + c_comment, + cxx_comment, + char_literal, + string_literal + }; + }; + + // code + // + bool code_counted_; + + //@@ gcc bug# 18304 + // + typename Construct::Value construct_; + }; + } +} + +//#include <backend-elements/indentation/sloc.txx> + +#endif // BACKEND_ELEMENTS_INDENTATION_SLOC_HXX |