void test_endfile (gfc_unit * u) { if (u->endfile == NO_ENDFILE && file_length (u->s) == file_position (u->s)) u->endfile = AT_ENDFILE; }
namespace quickbook { class value; class stored_value; class value_builder; class value_error; namespace detail { //////////////////////////////////////////////////////////////////////// // Node class value_node { private: value_node(value_node const&); value_node& operator=(value_node const&); public: typedef int tag_type; typedef boost::iterator_range<quickbook::iterator> qbk_range; protected: explicit value_node(tag_type); virtual ~value_node(); public: virtual char const* type_name() const = 0; virtual value_node* clone() const = 0; virtual value_node* store(); virtual file_position get_position() const; virtual std::string get_quickbook() const; virtual std::string get_boostbook() const; virtual qbk_range get_quickbook_range() const; virtual int get_int() const; virtual bool check() const; virtual bool empty() const; virtual bool is_list() const; virtual bool is_string() const; virtual bool equals(value_node*) const; virtual value_node* get_list() const; int ref_count_; const tag_type tag_; value_node* next_; friend void intrusive_ptr_add_ref(value_node* ptr) { ++ptr->ref_count_; } friend void intrusive_ptr_release(value_node* ptr) { if(--ptr->ref_count_ == 0) delete ptr; } }; //////////////////////////////////////////////////////////////////////// // Value base // // This defines most of the public methods for value. // 'begin' and 'end' are defined with the iterators later. class value_base { public: class iterator; typedef iterator const_iterator; typedef value_node::tag_type tag_type; enum { default_tag = 0 }; typedef boost::iterator_range<quickbook::iterator> qbk_range; protected: explicit value_base(value_node* base) : value_(base) { assert(value_); } ~value_base() {} void swap(value_base& x) { std::swap(value_, x.value_); } public: bool check() const { return value_->check(); } bool empty() const { return value_->empty(); } bool is_list() const { return value_->is_list(); } bool is_string() const { return value_->is_string(); } iterator begin() const; iterator end() const; // Item accessors int get_tag() const { return value_->tag_; } file_position get_position() const { return value_->get_position(); } std::string get_quickbook() const { return value_->get_quickbook(); } qbk_range get_quickbook_range() const { return value_->get_quickbook_range(); } std::string get_boostbook() const { return value_->get_boostbook(); } int get_int() const { return value_->get_int(); } // Equality is pretty inefficient. Not really designed for anything // more than testing purposes. friend bool operator==(value_base const& x, value_base const& y) { return x.value_->equals(y.value_); } protected: value_node* value_; // value_builder needs to access 'value_' to get the node // from a value. friend class quickbook::value_builder; friend class quickbook::stored_value; }; //////////////////////////////////////////////////////////////////////// // Reference and proxy values for use in iterators class value_ref : public value_base { public: explicit value_ref(value_node* base) : value_base(base) {} }; class value_proxy : public value_base { public: explicit value_proxy(value_node* base) : value_base(base) {} value_proxy* operator->() { return this; } value_ref operator*() const { return value_ref(value_); } }; //////////////////////////////////////////////////////////////////////// // Iterators class value_base::iterator : public boost::forward_iterator_helper< iterator, value, int, value_proxy, value_ref> { public: iterator(); explicit iterator(value_node* p) : ptr_(p) {} friend bool operator==(iterator x, iterator y) { return x.ptr_ == y.ptr_; } iterator& operator++() { ptr_ = ptr_->next_; return *this; } value_ref operator*() const { return value_ref(ptr_); } value_proxy operator->() const { return value_proxy(ptr_); } private: value_node* ptr_; }; inline value_base::iterator value_base::begin() const { return iterator(value_->get_list()); } inline value_base::iterator value_base::end() const { return iterator(); } //////////////////////////////////////////////////////////////////////// // Reference counting for values class value_counted : public value_base { value_counted& operator=(value_counted const&); protected: value_counted(); value_counted(value_counted const&); value_counted(value_base const&); value_counted(value_node*); ~value_counted(); }; //////////////////////////////////////////////////////////////////////// // List builder // // Values are immutable, so this class is used to build a list of // value nodes before constructing the value. class value_list_builder { value_list_builder(value_list_builder const&); value_list_builder& operator=(value_list_builder const&); public: value_list_builder(); value_list_builder(value_node*); ~value_list_builder(); void swap(value_list_builder& b); value_node* release(); void append(value_node*); void sort(); private: value_node* head_; value_node** back_; }; } //////////////////////////////////////////////////////////////////////////// // Value // // Most of the methods are in value_base. class value : public detail::value_counted { public: value(); value(value const&); value(detail::value_base const&); explicit value(detail::value_node*); value& operator=(value); void swap(value& x) { detail::value_counted::swap(x); } }; class stored_value : public detail::value_counted { public: stored_value(); stored_value(stored_value const&); stored_value(detail::value_base const&); stored_value& operator=(stored_value); void swap(stored_value& x) { detail::value_counted::swap(x); } }; // Empty value empty_value(value::tag_type = value::default_tag); // Integers value int_value(int, value::tag_type = value::default_tag); // Boostbook and quickbook strings value qbk_value(iterator, iterator, value::tag_type = value::default_tag); value qbk_value(std::string const&, file_position = file_position(), value::tag_type = value::default_tag); value bbk_value(std::string const&, value::tag_type = value::default_tag); value qbk_bbk_value(std::string const&, value::tag_type = value::default_tag); value qbk_bbk_value(iterator, iterator, std::string const&, value::tag_type = value::default_tag); //////////////////////////////////////////////////////////////////////////// // Value Builder // // Used to incrementally build a valueeter tree. class value_builder { public: value_builder(); void swap(value_builder& b); void save(); void restore(); value release(); void reset(); void set_tag(value::tag_type); void insert(value const&); void extend(value const&); void start_list(value::tag_type = value::default_tag); void finish_list(); void clear_list(); void sort_list(); private: detail::value_list_builder current; value::tag_type list_tag; boost::scoped_ptr<value_builder> saved; }; //////////////////////////////////////////////////////////////////////////// // Value Error // class value_error : public std::logic_error { public: explicit value_error(std::string const&); }; //////////////////////////////////////////////////////////////////////////// // Value Consumer // // Convenience class for unpacking value values. class value_consumer { public: class iterator : public boost::input_iterator_helper<iterator, boost::iterator_value<value::iterator>::type, boost::iterator_difference<value::iterator>::type, boost::iterator_pointer<value::iterator>::type, boost::iterator_reference<value::iterator>::type> { public: iterator(); explicit iterator(value::iterator* p) : ptr_(p) {} friend bool operator==(iterator x, iterator y) { return *x.ptr_ == *y.ptr_; } iterator& operator++() { ++*ptr_; return *this; } reference operator*() const { return **ptr_; } pointer operator->() const { return ptr_->operator->(); } private: value::iterator* ptr_; }; typedef iterator const_iterator; typedef iterator::reference reference; value_consumer(value const& x) : list_(x) , pos_(x.begin()) , end_(x.end()) {} value_consumer(reference x) : list_(x) , pos_(x.begin()) , end_(x.end()) {} reference consume() { assert_check(); return *pos_++; } reference consume(value::tag_type t) { assert_check(t); return *pos_++; } value optional_consume() { if(check()) { return *pos_++; } else { return value(); } } value optional_consume(value::tag_type t) { if(check(t)) { return *pos_++; } else { return value(); } } bool check() const { return pos_ != end_; } bool check(value::tag_type t) const { return pos_ != end_ && t == pos_->get_tag(); } void finish() const { if (pos_ != end_) throw value_error("Not all values handled."); } iterator begin() { return iterator(&pos_); } iterator end() { return iterator(&end_); } private: void assert_check() const { if (pos_ == end_) throw value_error("Attempt to read past end of value list."); } void assert_check(value::tag_type t) const { assert_check(); if (t != pos_->get_tag()) throw value_error("Incorrect value tag."); } value list_; value::iterator pos_, end_; }; }