#
# 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.libpackage 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 => []
};
};