/'* \file fb-doc_emitters.bi
\brief Header file for \ref EmitterIF

This file contains the declaration of the emitters interface, a UDT 
(User Defined Type) that contains function pointers. The \ref 
Parser calls the matching function in the active emitter after 
scanning a relevant construct. The emitter function extracts the 
necessary information from the parser data, formats it as desired 
and sends it to the output stream.

'/


CONST NL = !"\n"

/'* \brief Forward declaration '/
TYPE AS Parser Parser_

/'* \brief Function to emit a peace of code
\param P the parser calling this handler '/
TYPE EmitFunc AS SUB CDECL(BYVAL AS Parser_ PTR)

/'* \brief An empty emitter to initialize the interface
\param P the parser calling this handler '/
SUB null_emitter CDECL(BYVAL P AS Parser_ PTR) : END SUB

/'* \brief The emitter interface

The emitters interface is a UDT containing function pointers. The 
\ref Parser calls the matching function in the active emitter after 
scanning a relevant construct. The emitter function extracts the 
necessary information from the parser data, formats it as desired 
and sends it to the output stream.

Only one emitter can be active at a time. Either one of the four 
inbuild fb-doc emitters or an external emitter plugin can be choosen 
by option \em --emitter.

The function pointers get initialized with the null_emitter() 
function (SUB), that creates no output at all. Each emitter modul can
replace one or more of the pointers by a customized function to 
create a specific output.

Since Doxygen doesn't support to generate documentation for such an 
interface, it cannot create caller or callee graphs for the emitter 
functions. But we use fb-doc and can work-around this by creating 
additional C output in form of member function. These functions are 
unvisible for the FreeBasic compiler, but get emitted to the pseudo C
source for the Doxygen back-end and produce the desired output for 
the documentation.

'/
TYPE EmitterIF
Public:
  AS STRING Nam = ""  '*< the emitters name
'&/* Doxygen shouldn't parse this
  AS EmitFunc _
    Decl_ = @null_emitter, _
    Func_ = @null_emitter, _
    Enum_ = @null_emitter, _
    Unio_ = @null_emitter, _
    Clas_ = @null_emitter, _
    Defi_ = @null_emitter, _
    Incl_ = @null_emitter, _
   _Init_ = @null_emitter, _
  _Error_ = @null_emitter, _
  _Empty_ = @null_emitter, _
   _Exit_ = @null_emitter   
'& but instead the following pseudo inline menbers */

'* function called before parsing a source code
'& inline void _Init_ (void){c_Init(); geanyInit();};

'* emitter for a declaration (VAR / DIM / CONST / COMMON / EXTERN / STATIC)
'& inline void Decl_ (void){c_decl_(); gtk_decl_(); doxy_decl_(); callees_decl_();};

'* emitter for a function (SUB / FUNCTION / PROPERTY / CONSTRUCTOR / DESTRUCTOR)
'& inline void Func_ (void){c_func_(); gtk_func_(); doxy_func_(); callees_func_();};

'* emitter for a ENUM block
'& inline void Enum_ (void){c_Block(); gtk_Block(); doxy_Block();};

'* emitter for a UNION block
'& inline void Unio_ (void){c_Block(); gtk_Block(); doxy_Block(); callees_class_();};

'* emitter for a struct (TYPE / CLASS block)
'& inline void Clas_ (void){c_Block(); gtk_Block(); doxy_Block(); callees_class_();};

'* emitter for a macro (\#DEFINE / \#MACRO)
'& inline void Defi_ (void){c_defi_(); gtk_defi(); doxy_defi_();};

'* emitter for includes (\#INCLUDE)
'& inline void Incl_ (void){c_include(); callees_include();};

'* emitter for an error message
'& inline void _Error_ (void){c_error();};

'* emitter for an empty Geany block
'& inline void _Empty_ (void){gtk_empty(); doxy_empty();};

'* function called after parsing the source code
'& inline void _Exit_ (void){c_exit(); geanyExit();};
END TYPE


'* the array for the emitter interfaces
REDIM SHARED AS EmitterIF PTR Emitters(-1 TO -1)

CONST _
  COMM_END = NL & NL & "'/" & NL, _ '*< the end of an FB comment block (in templates)
     FIXME = "FIXME"                '*< the text to initialize entry fields (in templates)


/'* \brief Snippet to create a new \ref EmitterIF (for new customized emitter modules) '/
#MACRO WITH_NEW_EMITTER(_T_)
 REDIM PRESERVE Emitters(UBOUND(Emitters) + 1)
 Emitters(UBOUND(Emitters)) = NEW EmitterIF
 WITH *Emitters(UBOUND(Emitters))
  .Nam = _T_
#ENDMACRO
