ExpandedOutput.h
// ExpandedOutput.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2012
#pragma once
#ifndef Ceda_cxMacroExpander_ExpandedOutput_H
#define Ceda_cxMacroExpander_ExpandedOutput_H
#include "MacroExpand.h"
#include "cxMacroExpander.h"
#include "Ceda/cxUtils/BasicTypes.h"
#include "Ceda/cxUtils/CedaAssert.h"
#include "Ceda/cxUtils/xvector.h"
/*
The output of macro expansion is written using an xostream. However an xostream isn't adequate for
the additional functionality we require:
- Support for adjusting the indentation of text written to the output
- Auxilliary information to track where text came from in order to support error pinpointing.
Set of source files
-------------------
It is assumed there are a set of source files held in memory. Each source file records
1) The name - e.g. a fully qualified path
2) A string buffer - a single contiguous region of memory containing the content of the
file.
Given a
const char* errorpos
it is assumed we can readily test each source file in memory to see whether it contains that
position (this only requires two pointer comparisons and is very fast). After finding the relevent
file, we can count linefeeds up to that position to map the errorpos to a line number.
The conclusion is that we can record information about where text originates simply by using
pointers into the original source files, and that is all that is required to output paths and
line numbers efficiently enough for our needs.
Aux information for error pinpointing
-------------------------------------
Consider that the input to be macro expanded consists of text to be copied verbatim interspersed
with various directives.
input: -----------m1(...)-----------@str(m2(...)-----------@def m3={...}----@for(...){...}--------
output -----------****-----------**********-----------|----******--------
The output of macro expansion is divided into pieces. There are two kinds of pieces
1) Pieces that are copied verbatim from some input source file.
2) Pieces that are calculated - e.g. @str(factorial(5)) generates the piece "120". The characters
'1', '2' and '0' don't originate from any source file. Rather we say
"120" originates from "@str(factorial(5))" (where @str(factorial(5)) appears in some source
file).
*/
namespace ceda
{
class xostream;
///////////////////////////////////////////////////////////////////////////////////////////////////
// ExpandedOutput
// Intended to replace XcppParserOutputStream used by the XcppParser. The latter is the reason
// why this class is now exported by cxMacroExpander.
class cxMacroExpander_API ExpandedOutput
{
public:
explicit ExpandedOutput(xostream* os) :
m_os(os),
m_columnPos(-1),
m_size(0)
{
cxAssert(m_os);
}
ssize_t GetColumnPos() const { return m_columnPos; }
ssize_t size() const;
/*
Write 's' to the output using the given left indent position.
It is assumed s aliases part of a source file.
*/
void WriteSubStringFromSourceFile(SubString s, ssize_t dstIndent);
/*
Write 's' to the output using the given left indent position.
It is assumed s was calculated from a part of a source file identified by sSrcFile
*/
void WriteCalculatedSubString(SubString s, SubString sSrcFile, ssize_t dstIndent);
void GetPieces(OutputPieces& pieces)
{
pieces.swap(m_pieces);
}
private:
// If not NULL then this frame should generate output as tokens are scanned
xostream* m_os;
// Zero based column position in the output stream. Used to help with formatting output
// correctly.
// -1 means we have just started writing the output or a linefeed has just been output, so
// this condition triggers the writing of space characters according to the required
// destination indent.
ssize_t m_columnPos;
OutputPieces m_pieces;
ssize_t m_size;
};
} // namespace ceda
#endif // include guard