--- /dev/null
+#ifndef TAPE_BLOCK_H
+#define TAPE_BLOCK_H
+
+
+/*!
+ *\brief Tape data block base class
+ *
+ * This class represents a Honeywell paper tape block.
+ * That may be some kind of data block or a end of tape mark.
+ */
+class tape_block{
+
+public: // types
+
+ /*!
+ * The block's initialisation state
+ */
+ typedef enum {
+ TBS_OK, //!< Block successfully initialised
+ TBS_EOF_LEGAL, //!< Legal EOF while initialising
+ TBS_EOF_ILLEGAL, //!< Illegal EOF while initialising
+ TBS_CHECKSUM, //!< Checksum error
+ TBS_IOERR, //!< I/O-Error while reading
+ TBS_DEFAULT //!< Block not initialised.
+ } tb_state_t;
+
+ /*!
+ * Tape block types
+ */
+ typedef enum {
+ TBT_DATA=0x10, //!< Data block
+ TBT_EOT, //!< End of tape block
+ TBT_DISCARD //!< Invalid block, check block_type
+ } tb_type_t;
+
+protected: // methods
+ /*!
+ *\brief Protected default constructor
+ */
+ tape_block();
+
+public: // methods
+
+ tape_block(tape_block &);
+
+ /*!
+ *\brief Read-in constructor for file descriptor
+ *
+ * This constructor is used to read in the block's data via a file
+ * descriptor.\\
+ * This is done in the following way:\\
+ * - input_start() is called.\\
+ * - Data is read from fd. Stops on end of file or end of block
+ * or IO error. On EOF or IO error input_stop() is NOT called.\\
+ * - If there was no IO error the block's checksum is calculated
+ * and checked.\
+ * - The block's type field is initialised.\\
+ * - input_stop() is called.\\
+ *\param fd_p A pointer to the device descriptor where
+ * the data is taken from \\
+ *\param input_stop A pointer to a function called at the end of input\\
+ *\param input_start A pointer to a function called at the beginning
+ * of input\\
+ *\param start_stop_arg A pointer passed to input_start and input_stop().
+ */
+ tape_block (int fd_p,
+ void(*input_start)(void *)=0,
+ void (*input_stop)(void *)=0,
+ void * start_stop_arg=0
+ );
+
+ /*!
+ * The virtual destructor
+ */
+ virtual ~tape_block();
+
+ /*!
+ *\brief Query the block's state.
+ *
+ * If the state is not TBS_OK, the block must be discarded.
+ *\return The block's initialisation state
+ */
+ tb_state_t get_state();
+
+ /*!
+ *\brief Get size of the internal raw data buffer
+ *\return The size of the internal raw data buffer
+ */
+ int get_raw_size();
+
+ /*!
+ *\brief Access internal raw data buffer
+ *
+ * The raw data buffer contains all block data except the \\
+ * block start delimiter and block end delimiter.
+ *\return Pointer to internal raw data buffer of the block
+ */
+ unsigned char * get_raw_data();
+
+ /*
+ *\brief Determine the block's type
+ *
+ * This routine returns the block's type.\\
+ *\retval TBT_DATA if it's a data block
+ *\retval TBT_EOT if it's an end of tape mark
+ *\retval TBR_DISCARD if the block is unusable
+ *
+ *\note This function is virtual. That means that if the tape block in
+ * question is of the subtype data_block which overwrites this method,
+ * it will return the block type contained in the upper 4 bits of the
+ * first data word! Try to avoid testing for TBT_DATA.
+ */
+ virtual int get_type();
+
+ /*!
+ *\brief Determine the block's subtype
+ *
+ * Some data block types have a subtype. This can be determined this way.
+ *\return Block subtype if the block object is of a suitable subclass
+ */
+ virtual int get_subtype();
+
+private: // methods
+ /*!
+ *\brief Initialize word representation of data
+ *\retval 0 on success
+ *\retval 1 on error
+ */
+ int init_words(void);
+
+ /*!
+ *\brief Calculate and check checksum
+ *\retval 0 on success
+ *\retval 1 on error
+ */
+ int test_checksum();
+
+protected: // members
+ int block_type; //!< type of this block
+ tb_state_t init_state; //!< Initialisation state
+ int data_read; //!< Total data consumption during intialisation
+ unsigned char * raw_data; //!< Raw block data in bytes
+ int raw_size; //!< Size of the raw data
+ unsigned short * word_data; //!< Data organized in machine words
+ int word_size; //!< Size of the blocks in machine words
+
+}; // tape_block
+
+
+#endif