⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 writing_a_be

📁 这是广泛使用的通信开源项目,对于大容量,高并发的通讯要求完全能够胜任,他广泛可用于网络游戏医学图像网关的高qos要求.更详细的内容可阅读相应的材料
💻
📖 第 1 页 / 共 4 页
字号:
- The IDL input is preprocessed (in driver/drv_preproc.cc).
- FE initialization stage 1 is done: the scopes stack is created and stored
  in the global data variable idl_global->scopes() field (in fe/fe_init.cc).
- BE_init is called to create the generator instance and the returned
  instance is stored in the global data variable idl_global->gen() field.
- FE initialization stage 2 is done: the global scope is created, pushed on
  the scopes stack and populated with predefined types (in fe/fe_init.cc).

GLOBAL STATE AND ENTRY POINTS
-----------------------------

The CFE has one global variable named idl_global, which stores an instance
of a class IDL_GlobalData as explained below:

The CFE defines a class IDL_GlobalData which defines the global
information used in a specific run of the compiler. IDL_GlobalData is
defined in include/idl_global.hh and implemented in the file
util/utl_global.cc.

Initialization creates an instance of this class and stores it in the value
of the global variable idl_global. Thus, the individual pieces of
information stored in the instance are accessible everywhere.

ERROR HANDLING
--------------

All error handling is defined by a class provided by the CFE, UTL_Error.
This class is defined in include/utl_error.hh and implemented in the file
util/utl_error.cc. The class provides several methods for reporting
specific errors as well as generic error reporting methods taking zero to
three arguments.

The CFE instantiates the class and stores the instance as part of the
global state, accessible as idl_global->err(). Thus, to cause an error
report, you would write code similar to the following:

	if (error condition found)
	   idl_global->err()->specific_error_message(arg1, ..);

or

	if (error condition found)
	  idl_global->err()->generic_error_message(flag, arg1, ..);

The flag argument is one of the predefined error conditions found in the
enum at the head of the UTL_Error class definition. The arguments to the
specific error message routine are defined by the signature of that
routine. The arguments to a generic error message routine are always
instances of AST_Decl.

The running count of errors is accessible as idl_global->err_count(). If
the value returned by this operation is non-zero after the IDL input has
been parsed, the BE is not invoked.

HANDLING OF COMMAND LINE ARGUMENTS
----------------------------------

Defined command line arguments are specified in the document CLI, in this
directory. The CFE calls the required BE API entry point BE_prep_arg to
process arguments passed within a -Wb flag.

REQUIRED ENTRY POINTS SUPPLIED BY A BE
--------------------------------------

The following API entry points must be supplied by a BE in order to
successfully link with the CFE:

extern "C" AST_Generator   *BE_init();

       Creates an instance of the generator object and returns it. Note
       that the global scope is not yet set up and the scopes stack is
       empty when this routine is called.

extern "C" void		   BE_produce();

       Called by the compiler main program after the IDL input has been
       successfully parsed and processed. The job of this routine is to
       carry out the specific function of the BE. The AST is accessible as
       the value of idl_global->root().

extern "C" void	    	   BE_prep_arg(char *, idl_bool);

       Called to process an argument passed in with a -Wb flag. The boolean
       will always be FALSE.

extern "C" void	      	   BE_abort();

       Called when the CFE decides to abort the compilation. Can be used in
       a BE to clean up after itself, e.g. remove temporary files or
       directories it created while the parse was in progress.

extern "C" void	      	   BE_version();

       Called when a -V argument is processed. This should produce a
       message for the user identifying the BE that is loaded and its
       version information.

PART II. WRITING A BACK END
-=========================-

REQUIRED API THAT EACH BE MUST SUPPORT
--------------------------------------

Below are the API entry points that each BE must supply in order to use the
CFE framework. This is a repeat of the BE API section:

extern "C" AST_Generator   *BE_init();

       Creates an instance of the generator object and returns it. Note
       that the scopes stack is still not set up at the time this routine
       is called.

extern "C" void		   BE_produce();

       Called by the compiler main program after the IDL input has been
       successfully parsed and processed. The job of this routine is to
       carry out the specific function of the BE. The AST is accessible as
       the value of idl_global->root().

extern "C" void	    	   BE_prep_arg(char *, boolean);

       Called to process an argument passed in with a -Wb flag. The boolean
       will always be FALSE.

extern "C" void	      	   BE_abort();

       Called when the CFE decides to abort the compilation. Can be used in
       a BE to clean up after itself, e.g. remove temporary files or
       directories it created while the parse was in progress.

extern "C" void	      	   BE_version();

       Called when a -V argument is processed. This should produce a
       message for the user identifying the BE that is loaded and its
       version information.

WHAT FILES TO INCLUDE
---------------------

To use the CFE, each implementation file of your BE must include the
following two header files:

#include  <idl.hh>
#include  <idl_extern.hh>

Following this, you can include any header files needed by your BE.

HOW TO SUBCLASS THE AST
-----------------------

Your BE may subclass from any of the classes provided by the AST. Your
class should use public virtual inheritance to ensure that only one copy of
the class's data members is present in each instance. Read the section on
HOW TO WRITE CONSTRUCTORS to learn about additional considerations that you
must take into account when writing constructors for your BE classes.

HOW TO SUBCLASS THE GENERATOR TO CREATE BE ENHANCED AST NODES
-------------------------------------------------------------

Your BE subclasses from classes provided by the AST. To ensure that
instances of these classes are constructed when the AST is built, you must
also subclass AST_Generator and return an instance of your subclass from
the call to BE_init.

The AST_Generator class provides operations to create instances of all
classes defined in the AST. For example, the operation to create an
AST_Attribute node is as follows:

	AST_Attribute *
	AST_Generator::create_attribute(...)
	{
	  return new AST_Attribute(...);
	}

In your BE_Generator subclass of AST_Generator, you will override methods
for creation of nodes of all AST classes which you have subclassed. Thus,
if your BE has a class BE_Attribute which is a subclass of AST_Attribute,
your BE_Generator class definition has to override the create_attribute
method to ensure that instances of BE_Attribute are created.

The definition of the overriden operations should call the constructor of
the derived class and return the new node as an instance of the inherited
class. Thus, the implementation of create_attribute is as follows:

	AST_Attribute *
	BE_Generator::create_attribute(...)
	{
	  return new BE_Attribute(...);
	}

The Yacc grammar actions call create_xxx operations on the generator
instance stored in the global variable idl_global->gen() field. By storing
an instance of your derived generator class BE_Generator you ensure that
instances of the BE classes you defined will be created.

HOW TO WRITE CONSTRUCTORS FOR BE CLASSES
----------------------------------------

As mentioned above, the AST uses public virtual inheritance to derive the
AST class hierarchy. This has two important effects on how you write a BE,
specifically how you write constructors for derived BE classes.

First, you must define a default constructor for your BE class, since
your class may be used as a virtual base class of some other class. In that
case the compiler may want to call a default constructor for your class. It
is a good idea to have a default constructor anyway, even if you do not
plan to subclass your BE class, since for most C++ compilers this causes
the code to be smaller. Your default constructor should initialize all
constant data members. Additionally, it may initialize any non-constant
data member whose value must be set before the first time the instance is
used.

Second, the constructor for your BE class must explicitly call all
constructors of virtual base classes which do some useful work. For
example, if a class in the AST from which your BE class inherits, directly
or indirectly, has an initializer for a data member, your BE class's
constructor must call the AST class's constructor. This is discussed
extensively in the C++ ARM.

Below is a list showing how to write constructors for subclasses of each
class provided by the BE. For each AST class we show a definition of a
constructor for a derived class which calls all neccessary constructors on
AST classes:

AST_Argument:

	BE_Argument::BE_Argument(AST_Argument::Direction d,
				 AST_Type *ft,
				 UTL_ScopedName *n,
				 UTL_StrList *p)
		   : AST_Argument(d, ft, n, p),
		     AST_Field(AST_Decl::NT_argument, ft, n, p),
		     AST_Decl(AST_Decl::NT_argument, n, p)
	{
	}

AST_Array:

	BE_Array::BE_Array(UTL_ScopedName *n,
			   unsigned long nd,
			   UTL_ExprList *ds)
		: AST_Array(n, nd, ds),
		  AST_Decl(AST_Decl::NT_array, n, NULL)

	{
	}

AST_Attribute:

	BE_Attribute::BE_Attribute(boolean ro,
				   AST_Type *ft,
				   UTL_ScopedName *n,
				   UTL_StrList *p)
		    : AST_Attribute(ro, ft, n, p),
		      AST_Field(AST_Decl::NT_attr, ft, n, p),
		      AST_Decl(AST_Decl::NT_attr, n, p)
	{
	}

AST_ConcreteType:

	BE_ConcreteType::BE_ConcreteType(AST_Decl::NodeType nt,
					 UTL_ScopedName *n,
					 UTL_StrList *p)
		       : AST_Decl(nt, n, p)
	{
	}

AST_Constant:

	BE_Constant::BE_Constant(AST_Expression::ExprType t,
				 AST_Expression *v,
				 UTL_ScopedName *n,
				 UTL_StrList *p)
		   : AST_Constant(t, v, n, p),
		     AST_Decl(AST_Decl::NT_const, n, p)
	{
	}

AST_Decl:

	BE_Decl::BE_Decl(AST_Decl::NodeType nt,
			 UTL_ScopedName *n,
			 UTL_StrList *p)
	       : AST_Decl(nt, n, p)
	{
	}

AST_Enum:

	BE_Enum::BE_Enum(UTL_ScopedName *n,
			 UTL_StrList *p)
	       : AST_Enum(n, p),
		 AST_Decl(AST_Decl::NT_enum, n, p),
		 UTL_Scope(AST_Decl::NT_enum)
	{
	}

AST_EnumVal:

	BE_EnumVal::BE_EnumVal(unsigned long v,
			       UTL_ScopedName *n,
			       UTL_StrList *p)
		  : AST_EnumVal(v, n, p),
		    AST_Constant(AST_Expression::EV_ulong,
		    		 AST_Decl::NT_enum_val,
				 new AST_Expression(v),
				 n,
				 p),
		    AST_Decl(AST_Decl::NT_enum_val, n, p)
	{
	}

AST_Exception:

	BE_Exception::BE_Exception(UTL_ScopedName *n,
				   UTL_StrList *p)
		    : AST_Decl(AST_Decl::NT_except, n, p),
		      AST_Structure(AST_Decl::NT_except, n, p),
		      UTL_Scope(AST_Decl::NT_except)
	{
	}

AST_Field:

	BE_Field::BE_Field(AST_Type *ft,
			   UTL_ScopedName *n,
			   UTL_StrList *p)
		: AST_Field(ft, n, p),
		  AST_Decl(AST_Decl::NT_field, n, p)
	{
	}

AST_Interface:

	BE_Interface::BE_Interface(UTL_ScopedName *n,
				   AST_Interface **ih,
				   long nih,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -