PreviousUpNext

15.4.22  src/app/c-glue-maker/spec.pkg

#
# spec.pkg - A data package describing the
#            export interface of a C program.
#
#  (C) 2001, Lucent Technologies, Bell Labs
#
# author: Matthias Blume (blume@research.bell-labs.com)

# Compiled by:
#     src/app/c-glue-maker/c-glue-maker.lib

package spec {


    Constness = RO      # C "const" makes something be RO ("read only").
              | RW;     # Anything not RO is RW ("read/write").

    Cname = String;



    # The base types defined by Ansi C:

    Ctype = UCHAR     | SCHAR           # un/signed char.
          | UINT      | SINT            # un/signed int.
          | USHORT    | SSHORT          # un/signed short.
          | ULONG     | SLONG           # un/signed long.
          | ULONGLONG | SLONGLONG       # un/signed long long.
          | FLOAT
          | DOUBLE
          | VOIDPTR                     # void*
          | STRUCT  Cname
          | UNION   Cname
          | ENUM   (Cname, Bool)
          | FPTR  Cft                   # Function pointers.
          | PTR  Cchunk
          | ARR  { t: Ctype, d: Int, esz: Int }
          | UNIMPLEMENTED  String

    withtype
    Cft =                               # C function types
        { args:   List( Ctype ),
          result: Null_Or( Ctype )
        }

    also
    Cchunk = (Constness, Ctype);

    Fieldspec = OFIELD                  { offset: Int,  spec: Cchunk,  synthetic: Bool }                        # OFIELD == "ordinary field"
              | SIGNED_BITFIELD         { offset: Int,  constness: Constness,  bits: Unt,  shift: Unt }
              | UNSIGNED_BITFIELD       { offset: Int,  constness: Constness,  bits: Unt,  shift: Unt };

    Field = { name: String,
              spec: Fieldspec
            };

    Enumval
        =
        { name: String,
          spec: large_int::Int
        };

    Type_Struct
        =
        { src:     String,
          c_name:  Cname,
          anon:    Bool,
          size:    Unt,
          fields:  List( Field ),
          exclude: Bool
        };

    Type_Union
        =
        { src:     String,
          c_name:  Cname,
          anon:    Bool,
          size:    Unt,
          all:     List( Field ),
          exclude: Bool
        };

    Type_Enum
        =
        { src:     String,
          c_name:  Cname,
          anon:    Bool,
          descr:   String,
          spec:    List( Enumval ),
          exclude: Bool
        };

    Global_Variable
        =
        { src:    String,
          c_name: String,
          spec:   Cchunk
        };

    Global_Function
        = { src:       String,
            c_name:    String,
            spec:      Cft,
            arg_names: Null_Or(  List(  String ) )
          };

    Global_Type
        =
        { src:    String,
          c_name: String,
          spec:   Ctype
        };


    # A 'Spec' gives the complete external interface
    # for all the functions, values and types exported
    # by one or more C source files.
    #
    # This is logically a single declaration list,
    # but for ease of processing we break it up
    # into multiple lists segretated by type:

    Spec
        =
        { structs:          List( Type_Struct     ),
          unions:           List( Type_Union      ),
          enums:            List( Type_Enum       ),
          global_types:     List( Global_Type     ),
          global_variables: List( Global_Variable ),
          global_functions: List( Global_Function )
        };

    # Merge contents of two 'Spec' values:
    fun join ( x: Spec,
               y: Spec
             )
        =
        {   # Merge two lists, dropping duplicates.
            #
            # The list elements are records;
            # We look at only one field per record,
            # that String extracted by 'selector':

            fun uniq selector
                =
                loop
                where
                    fun loop ([], results)
                            =>
                            reverse results;

                        loop (h ! t, results)
                            =>
                            loop (
                                t,

                                if  (list::exists
                                         (\\ x =  (selector x:  String) == selector h)
                                         results
                                    )

                                     results;
                                else
                                     h ! results;
                                fi
                            );
                    end;
                end;

            { structs          =>  uniq  .c_name  (x.structs,            y.structs         ),
              unions           =>  uniq  .c_name  (x.unions,             y.unions          ),
              enums            =>  uniq  .c_name  (x.enums,              y.enums           ),
              global_types     =>  uniq  .c_name  (x.global_types,       y.global_types    ),
              global_variables =>  uniq  .c_name  (x.global_variables,   y.global_variables),
              global_functions =>  uniq  .c_name  (x.global_functions,   y.global_functions)

            }: Spec;
        };

    my empty:  Spec = { structs           => [],
                        unions            => [],
                        enums             => [],
                        global_types      => [],
                        global_variables  => [],
                        global_functions  => []
                      };
};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext