Man Linux: Main Page and Category List

NAME

       gencls - class interface compiler for Prima core modules

SYNOPSIS

         gencls --h --inc --tml -O -I<name> --depend --sayparent filename.cls

DESCRIPTION

       Creates headers with C macros and structures for Prima core module
       object definitions.

ARGUMENTS

       gencls accepts the following arguments:

       --h Generates .h file ( with declarations to be included in one or more
           files )

       --inc
           Generates .inc file ( with declarations to be included in only file
           )

       -O  Turns optimizing algorithm for .inc files on. Algorithm is based on
           an assumption, that some functions are declared identically,
           therefore the code piece that handles the parameter and result
           conversion can be shared. With "-O" flag on, a thunk body is
           replaced to a call to a function, which name is made up from all
           method parameters plus result.  Actual function is not written in
           .inc file, but in .tml file.  All duplicate declarations from a set
           of .tml files can be removed and the reminder written to one file
           by tmlink utility.

       --tml
           Generates .tml file. Turns "-O" automatically on.

       -Idirname
           Adds a directory to a search path, where the utility searches for
           .cls files. Can be specified several times.

       --depend
           Prints out dependencies for a given file.

       --sayparent
           Prints out the immediate parent of a class inside given file.

SYNTAX

       In short, the syntax of a .cls file can be described by the following
       scheme:

         [ zero or more type declarations ]
         [ zero or one class declaration ]

       Gencls produces .h, .inc or .tml files, with a base name of the .cls
       file, if no object or package name given, or with a name of the object
       or the package otherwise.

   Basic scalar data types
       Gencls has several built-in scalar data types, that it knows how to
       deal with. To ’deal’ means that it can generate a code that transfers
       data of these types between C and perl, using XS ( see perlguts )
       library interface.

       The types are:

          int
          Bool
          Handle
          double
          SV*
          HV*
          char *
          string ( C declaration is char[256] )

       There are also some derived built-in types, which are

          long
          short
          char
          Color
          U8

       that are mapped to int. The data undergo no conversion to int in
       transfer process, but it is stored instead to perl scalar using
       newSViv() function, which, in turn, may lose bits or a sign.

   Derived data types
       The syntax for a new data types definition is as follows:

          <scope> <prefix> <id> <definition>

       A scope can be one of two pragmas, "global" or "local".  They hint the
       usage of a new data type, whether the type will be used only for one or
       more objects. Usage of "local" is somewhat resembles C pragma static.
       Currently the only difference is that a function using a complex local
       type in the parameter list or as the result is not a subject for "-O"
       optimization.

   Scalar types
       New scalar types may only be aliased to the existing ones, primarily
       for C coding convenience.  A scalar type can be defined in two ways:

       Direct aliasing
           Syntax:

             <scope> $id => <basic_scalar_type>;

           Example:

             global $Handle => int;

           The new type id will not be visible in C files, but the type will
           be substituted over all .cls files that include this definition.

       C macro
           Syntax:

             <scope> id1 id2

           Example:

             global API_HANDLE UV

           Such code creates a C macro definition in .h header file in form

             #define id1 id2

           C macros with parameters are not allowed. id1 and id2 are not
           required to be present in .cls name space, and no substitution
           during .cls file processing is made.  This pragma usage is very
           limited.

   Complex types
       Complex data types can be arrays, structs and hashes.  They can be a
       combination or a vector of scalar ( but not complex) data types.

       Gencls allows several combinations of complex data types that C
       language does not recognize. These will be described below.

       Complex data types do not get imported into perl code.  A perl
       programmer must conform to the data type used when passing parameters
       to a function.

       Arrays
           Syntax:

             <scope> @id <basic_scalar_type>[dimension];

           Example:

             global @FillPattern U8[8];

           Example of functions using arrays:

             Array * func( Array a1, Array * a2);

           Perl code:

             @ret = func( @array1, @array2);

           Note that array references are not used, and the number of items in
           all array parameters must be exactly as the dimensions of the
           arrays.

           Note: the following declaration will not compile with C compiler,
           as C cannot return arrays. However it is not treated as an error by
           gencls:

             Array func();

       Structs
           Syntax:

             <scope> @id {
                <basic_scalar_type> <id>;
                ...
                <basic_scalar_type> <id>;
             };

           Example:

             global @Struc {
                int    number;
                string id;
             }

           Example of functions using structs:

             Struc * func1( Struc a1, Struc * a2);
             Struc   func2( Struc a1, Struc * a2);

           Perl code:

             @ret = func1( @struc1, @struc2);
             @ret = func2( @struc1, @struc2);

           Note that array references are not used, and both number and order
           of items in all array parameters must be set exactly as dimensions
           and order of the structs. Struct field names are not used in perl
           code as well.

       Hashes
           Syntax:

             <scope> %id {
                <basic_scalar_type> <id>;
                ...
                <basic_scalar_type> <id>;
             };

           Example:

             global %Hash {
                int    number;
                string id;
             }

           Example of functions using hashes:

             Hash * func1( Hash a1, Hash * a2);
             Hash   func2( Hash a1, Hash * a2);

           Perl code:

             %ret = %{func1( \%hash1, \%hash2)};
             %ret = %{func2( \%hash1, \%hash2)};

           Note that only hash references are used and returned.  When a hash
           is passed from perl code it might have some or all fields unset.
           The C structure is filled and passed to a C function, and the
           fields that were unset are assigned to a corresponding C_TYPE_UNDEF
           value, where TYPE is one of NUMERIC, STRING and POINTER literals.

           Back conversion does not count on these values and always returns
           all hash keys with a corresponding pair.

   Namespace section
       Syntax:

          <namespace> <ID> {
             <declaration>
             ...
             <declaration>
          }

       A .cls file can have zero or one namespace sections, filled with
       function descriptions. Functions described here will be exported to the
       given ID during initialization code. A namespace can be either "object"
       or "package".

       The package namespace syntax allows only declaration of functions
       inside a "package" block.

           package <Package ID> {
               <function description>
               ...
           }

       The object namespace syntax includes variables and properties as well
       as functions ( called methods in the object syntax ).  The general
       object namespace syntax is

           object <Class ID> [(Parent class ID)] {
              <variables>
              <methods>
              <properties>
           }

       Within an object namespace the inheritance syntax can be used:

           object <Class ID> ( <Parent class ID>)  { ... }

       or a bare root object description ( with no ancestor )

           object <Class ID> { ... }

       for the object class declaration.

   Functions
       Syntax:

           [<prefix>] <type> <function_name> (<parameter list>) [ => <alias>];

       Examples:

               int   package_func1( int a, int b = 1) => c_func_2;
               Point package_func2( Struc * x, ...);
        method void  object_func3( HV * profile);

       A prefix is used with object functions ( methods ) only.  More on the
       prefix in Methods section.

       A function can return nothing ( void ), a scalar ( int, string, etc )
       or a complex ( array, hash ) type. It can as well accept scalar and
       complex parameters, with type conversion that corresponds to the rules
       described above in "Basic scalar data types" section.

       If a function has parameters and/or result of a type that cannot be
       converted automatically between C and perl, it gets declared but not
       exposed to perl namespace.  The corresponding warning is issued.  It is
       not possible using gencls syntax to declare a function with custom
       parameters or result data.  For such a purpose the explicit C
       declaration of code along with "newXS" call must be made.

       Example: ellipsis (...) cannot be converted by gencls, however it is a
       legal C construction.

         Point package_func2( Struc * x, ...);

       The function syntax has several convenience additions:

       Default parameter values
           Example:

             void func( int a = 15);

           A function declared in such way can be called both with 0 or 1
           parameters. If it is called with 0 parameters, an integer value of
           15 will be automatically used.  The syntax allows default
           parameters for types int, pointer and string and their scalar
           aliases.

           Default parameters can be as many as possible, but they have to be
           in the end of the function parameter list.  Declaration "func( int
           a = 1, int b)" is incorrect.

       Aliasing
           In the generated C code, a C function has to be called after the
           parameters have been parsed. Gencls expects a conformant function
           to be present in C code, with fixed name and parameter list.
           However, if the task of such function is a wrapper to an identical
           function published under another name, aliasing can be preformed to
           save both code and speed.

           Example:

              package Package {
                 void func( int x) => internal;
              }

           A function declared in that way will not call Package_func() C
           function, but internal() function instead. The only request is that
           internal() function must have identical parameter and result
           declaration to a func().

       Inline hash
           A handy way to call a function with a hash as a parameter from perl
           was devised. If a function is declared with the last parameter or
           type "HV*", then parameter translation from perl to C is performed
           as if all the parameters passed were a hash. This hash is passed to
           a C function and it’s content returned then back to perl as a hash
           again.  The hash content can be modified inside the C function.

           This declaration is used heavily in constructors, which perl code
           is typical

              sub init
              {
                 my %ret = shift-> SUPER::init( @_);
                 ...
                 return %ret;
              }

           and C code is usually

              void Obj_init ( HV * profile) {
                  inherited init( profile);
                  ... [ modify profile content ] ...
              }

   Methods
       Methods are functions called in a context of an object.  Virtually all
       methods need to have an access to an object they are dealing with.
       Prima objects are visible in C as Handle data type. Such Handle is
       actually a pointer to an object instance, which in turn contains a
       pointer to the object virtual methods table ( VMT ).  To facilitate an
       OO-like syntax, this Handle parameter is almost never mentioned in all
       methods of an object description in a cls file, although being implicit
       counted, so every cls method declaration

          method void a( int x)

       for an object class Object is reflected in C as

          void Object_a( Handle self, int x)

       function declaration. Contrary to package functions, that gencls is
       unable to publish if it is unable to deal with the unsupported on
       unconvertible parameters, there is a way to issue such a declaration
       with a method. The primary use for that is the method name gets
       reserved in the object’s VMT.

       Methods are accessible in C code by the direct name dereferencing of a
       "Handle self" as a corresponding structure:

           ((( PSampleObject) self)-> self)-> sample_method( self, ...);

       A method can have one of six prefixes that govern C code generation:

       method
           This is the first and the most basic method type.  It’s prefix
           name, "method" is therefore was chosen as the most descriptive
           name. Methods are expected to be coded in C, the object handle is
           implicit and is not included into a .cls description.

              method void a()

           results in

              void Object_a( Handle self)

           C declaration. A published method automatically converts its
           parameters and a result between C and perl.

       public
           When the methods that have parameters and/or result that cannot be
           automatically converted between C and perl need to be declared, or
           the function declaration does not fit into C syntax, a "public"
           prefix is used. The methods declared with "public" is expected to
           communicate with perl by means of XS ( see perlxs ) interface. It
           is also expected that a "public" method creates both REDEFINED and
           FROMPERL functions ( see Prima::internals  for details). Examples
           are many throughout Prima source, and will not be shown here.
           "public" methods usually have void result and no parameters, but
           that does not matter much, since gencls produces no conversion for
           such methods.

       import
           For the methods that are unreasonable to code in C but in perl
           instead, gencls can be told to produce the corresponding wrappers
           using "import" prefix. This kind of a method can be seen as
           "method" inside-out. "import" function does not need a C
           counterpart, except the auto-generated code.

       static
           If a method has to be able to work both with and without an object
           instance, it needs to be prepended with "static" prefix.  "static"
           methods are all alike "method" ones, except that "Handle self"
           first parameter is not implicitly declared.  If a "static" method
           is called without an object ( but with a class ), like

              Class::Object-> static_method();

           its first parameter is not a object but a "Class::Object" string.
           If a method never deals with an object, it is enough to use its
           declaration as

              static a( char * className = "");

           but is if does, a

              static a( SV * class_or_object = nil);

           declaration is needed. In latter case C code itself has to
           determine what exactly has been passed, if ever. Note the default
           parameter here: a "static" method is usually legible to call as

             Class::Object::static_method();

           where no parameters are passed to it. Without the default parameter
           such a call generates an ’insufficient parameters passed’ runtime
           error.

       weird
           We couldn’t find a better name for it. "weird" prefix denotes a
           method that combined properties both from "static" and "public". In
           other words, gencls generates no conversion code and expects no
           "Handle self" as a first parameter for such a method. As an example
           Prima::Image::load can be depicted, which can be called using a
           wide spectrum of calling semantics ( see Prima::image-load for
           details).

       c_only
           As its name states, "c_only" is a method that is present on a VMT
           but is not accessible from perl. It can be overloaded from C only.
           Moreover, it is allowed to register a perl function with a name of
           a "c_only" method, and still these entities will be wholly
           independent from each other - the overloading will not take place.

           NB: methods that have result and/or parameters data types that can
           not be converted automatically, change their prefix to "c_only".
           Probably this is the wrong behavior, and such condition have to
           signal an error.

   Properties
       Prima toolkit introduces an entity named property, that is expected to
       replace method pairs whose function is to acquire and assign some
       internal object variable, for example, an object name, color etc.
       Instead of having pair of methods like Object::set_color and
       Object::get_color, a property Object::color is devised. A property is a
       method with the special considerations, in particular, when it is
       called without parameters, a ’get’ mode is implied. In contrary, if it
       is called with one parameter, a ’set’ mode is triggered. Note that on
       both ’set’ and ’get’ invocations "Handle self" first implicit parameter
       is always present.

       Properties can operate with different, but fixed amount of parameters,
       and perform a ’set’ and ’get’ functions only for one. By default the
       only parameter is the implicit "Handle self":

          property char * name

       has C counterpart

          char * Object_name( Handle self, Bool set, char * name)

       Depending on a mode, "Bool set" is either "true" or "false".  In ’set’
       mode a C code result is discarded, in ’get’ mode the parameter value is
       undefined.

       The syntax for multi-parameter property is

          property long pixel( int x, int y);

       and C code

          long Object_pixel( Handle self, Bool set, int x, int y, long pixel)

       Note that in the multi-parameter case the parameters declared after
       property name are always initialized, in both ’set’ and ’get’ modes.

   Instance variables
       Every object is characterized by its unique internal state.  Gencls
       syntax allows a variable declaration, for variables that are allocated
       for every object instance. Although data type validation is not
       performed for variables, and their declarations just get copied ’as
       is’, complex C declarations involving array, struct and function
       pointers are not recognized.  As a workaround, pointers to typedef’d
       entities are used.  Example:

          object SampleObject {
             int x;
             List list;
             struct { int x } s; # illegal declaration
          }

       Variables are accessible in C code by direct name dereferencing of a
       "Handle self" as a corresponding structure:

           (( PSampleObject) self)-> x;

AUTHORS

       Dmitry Karasik, <dmitry@karasik.eu.org>.  Anton Berezin,
       <tobez@tobez.org>.

SEE ALSO

       Prima::internals, tmlink

COPYRIGHT

       This program is distributed under the BSD License.