Prima
view release on metacpan or search on metacpan
Prima/sys/Gencls.pm view on Meta::CPAN
next;
} elsif ( $tok eq 'define') {
parse_define( $global);
next;
}
putback( $tok2);
putback( $tok);
} elsif ( $tok eq 'use') {
my $fid = getid;
expect(';');
save_context;
my $loaded;
foreach (@includeDirs) {
my $f = "$_/$fid.cls";
next unless -f $f;
$loaded = $f;
}
die "$fid.cls not found\n" unless defined $loaded;
load_file( $loaded);
$level++;
&load_structures;
$level--;
restore_context;
} else {
putback ( $tok);
last;
}
}
}
#start of parse_file
load_file( shift);
load_structures;
$tok = gettok;
if (( $tok eq "object") || ( $tok eq "package")) {
load_single_part( $tok);
} elsif ( $tok) {
error "found $tok but expecting 'object' or 'package'";
} else {
unless ( $level) {
#$genInc = 0;
$ownFile = $fileName;
$ownFile =~ s/([^.]*)\..*$/$1/;
my $out = $ownFile;
$out =~ s[.*\/][];
$ownCType = uc $out;
}
}
} # end of parse_file
sub type2sv
{
my ( $type, $name) = @_;
$type = $mapTypes{ $type} || $type;
if ( ref $type) {
return "sv_$type->[PROPS]->{name}2HV(&($name))";
} elsif ( $type eq 'Handle') {
return "( $name ? (( $incInst)$name)-> $hMate : &PL_sv_undef)";
} elsif ( $type eq 'string') {
my $fname = $name;
$fname =~ s/(.*)\b(\w+)$/${1}is_utf8.$2/;
return "prima_svpv_utf8($name, $fname)";
} elsif ( $type eq 'SV*') {
return $name;
} else {
return "new${xsConv{$type}[7]}( $name$xsConv{$type}[5])";
}
}
sub sv2type
{
my ( $type, $name) = @_;
$type = $mapTypes{ $type} || $type;
if ( $type eq 'Handle') {
return "$incGetMate( $name);";
} elsif ( $type eq 'SV*') {
return $name;
} else {
return "$xsConv{$type}[1]( $name$xsConv{$type}[8])";
}
}
sub sv2type_pop
{
my ( $type) = @_;
$type = $mapTypes{ $type} || $type;
if ( $type eq 'Handle') {
return "$incGetMate( POPs);";
} elsif ( $type eq 'SV*') {
return 'POPs';
} else {
return "( $xsConv{$type}[0]) $xsConv{$type}[6]";
}
}
sub mortal
{
my $type = $mapTypes{ $_[0]} || $_[0];
if ( $type eq 'SV*') {
return '';
} elsif ( $type eq 'Handle') {
return 'sv_mortalcopy';
} else {
return 'sv_2mortal';
}
}
sub cwrite
{
my ( $type, $from, $to) = @_;
$type = $mapTypes{ $type} || $type;
if ( $type eq 'string') {
return "strncpy( $to, $from, 255); $to\[255\]=0;";
} else {
return "$to = $from;";
}
}
sub out_method_profile
# common method print sub
{
Prima/sys/Gencls.pm view on Meta::CPAN
open HEADER, ">$dirOut$out.h" or die "Cannot open $dirOut$out.h\n";
print HEADER <<LABEL;
/* This file was automatically generated.
* Do not edit, you\'ll lose your changes anyway.
* file: $out.h */
#ifndef ${ownCType}_H_
#define ${ownCType}_H_
#ifndef _APRICOT_H_
#include \"apricot.h\"
#endif
LABEL
# struct
print HEADER "#include \"$baseFile.h\"\n" if $baseClass;
{
my %toInclude = ();
for ( sort {
$structs{$a}-> [PROPS]-> {order} <=> $structs{$b}-> [PROPS]-> {order}
} keys %structs) {
my $f = ${$structs{$_}[PROPS]}{incl};
$toInclude{$f}=1 if $f;
}
for ( keys %arrays) {
my $f = ${$arrays{$_}[2]}{incl};
$toInclude{$f}=1 if $f;
}
for ( keys %defines) {
my $f = $defines{$_}{incl};
$toInclude{$f}=1 if $f;
}
for ( keys %mapTypes) {
my $f = $typedefs{$_}{incl};
$toInclude{$f}=1 if $f;
}
for ( keys %toInclude) {
s[.*\/][];
print HEADER "#include \"$_.h\"\n";
}
}
print HEADER "\n";
print HEADER <<SD;
#ifdef __cplusplus
extern "C" {
#endif
SD
# generating inplaced structures
for ( sort { $structs{$a}-> [PROPS]-> {order} <=> $structs{$b}-> [PROPS]-> {order}} keys %structs)
{
my $s = $structs{$_};
if ( $$s[PROPS]{genh})
{
my @types = @{$$s[TYPES]};
my @ids = @{$$s[IDS]};
my @def = @{$$s[DEFS]};
print HEADER "typedef struct _$_ {\n";
my ($maxw_undefs, @undefs) = (0);
my ($maxw_utfs, @utfs) = (0);
for ( my $j = 0; $j < @types; $j++) {
if ( ref $types[$j]) {
print HEADER "\t$types[$j]->[PROPS]->{name} $ids[$j];\n";
} elsif ( $types[$j] eq "string") {
print HEADER "\tchar $ids[$j]\[256\];\n";
push @utfs, $ids[$j];
$maxw_utfs = length $ids[$j] if length($ids[$j]) > $maxw_utfs;
} else {
print HEADER "\t$types[$j] $ids[$j];\n";
}
if (($def[$j] // '') =~ /^undef:/) {
push @undefs, $ids[$j];
$maxw_undefs = length $ids[$j] if length($ids[$j]) > $maxw_undefs;
}
}
my $wtab = $maxw_undefs // 0;
$wtab = $maxw_utfs if ($maxw_utfs // 0) > $wtab;
if ( @undefs ) {
print HEADER "\tstruct {\n";
printf HEADER "\t\tunsigned %\-${wtab}s : 1;\n", $_ for @undefs;
print HEADER "\t} undef;\n";
}
if ( @utfs ) {
print HEADER "\tstruct {\n";
printf HEADER "\t\tunsigned %\-${wtab}s : 1;\n", $_ for @utfs;
print HEADER "\t} is_utf8;\n";
}
print HEADER "} $_, *P$_;\n\n";
if ( $$s[PROPS]{hash})
{
print HEADER "extern $_ * SvHV_$_( SV * hashRef, $_ * strucRef, const char * errorAt);\n";
print HEADER "extern SV * sv_${_}2HV( $_ * strucRef);\n";
}
print HEADER "extern $_ ${_}_buffer;\n\n";
}
}
# generating inplaced arrays
for ( keys %arrays)
{
if ( ${$arrays{$_}[2]}{genh})
{
print HEADER "typedef $arrays{$_}[1] $_\[ $arrays{$_}[0]\];\n";
print HEADER "extern $_ ${_}_buffer;\n\n";
}
}
# and typedefs
for ( keys %mapTypes)
{
if ( $typedefs{$_}{genh})
{
print HEADER "typedef $mapTypes{$_} $_;\n" unless $typedefs{$_}{cast};
}
}
# defines
for ( keys %defines)
{
if ( $defines{$_}{genh})
{
print HEADER "#define $_ $defines{$_}{type}\n";
}
}
if ( $genObject)
{
print HEADER <<LABEL;
typedef struct _${ownCType}_vmt {
/* internal runtime classifiers */
char *$hClassName;
void *$hSuper;
void *$hBase;
int $hSize;
VmtPatch *patch;
int patchLength;
int vmtSize;
/* methods definition */
LABEL
for ( my $i = 0; $i <= $#allMethods; $i++)
{
my $body = $allMethodsBodies[ $i];
my $id = $allMethods[ $i];
$body =~ s/\b$id\b/\( \*$id\)/;
print HEADER "\t$body\n";
}
print HEADER <<LABEL;
Prima/sys/Gencls.pm view on Meta::CPAN
LABEL
print HEADER "#include \"guts.h\"\n" if ( !$genDyna && $genObject);
print HEADER <<SD;
#ifdef __cplusplus
extern "C" {
#endif
SD
out_FROMPERL_methods( \@portableMethods, 1); # portable methods, bodies
my %newH = (%structs, %arrays);
for ( keys %newH)
{
print HEADER "$_ ${_}_buffer;\n" if ( ${$newH{$_}[2]}{genh});
}
print HEADER "\n\n";
# generating SvHV_hash & sv_hash2HV, if any
for ( sort { $structs{$a}-> [PROPS]-> {order} <=> $structs{$b}-> [PROPS]-> {order}} keys %structs)
{
my $S = $_;
my $s = $structs{$S};
if ( $s->[PROPS]->{genh} && $s->[PROPS]->{hash})
{
print HEADER "$S * SvHV_$S( SV * hashRef, $S * strucRef, const char * errorAt)\n{\n";
print HEADER "\tconst char * err = errorAt ? errorAt : \"$S\";\n";
print HEADER "\tHV * $incHV = ( HV*)\n\t".
"(( SvROK( hashRef) && ( SvTYPE( SvRV( hashRef)) == SVt_PVHV)) ? SvRV( hashRef)\n\t\t".
": ( croak( \"Illegal hash reference passed to %s\", err), NULL));\n";
print HEADER "\tSV ** $incSV;\n\n\t(void)$incSV;\n\n";
for ( my $j = 0; $j < scalar @{$s->[TYPES]}; $j++)
{
my $lType = @{ $s->[TYPES]}[$j];
my $lName = @{ $s->[IDS]}[$j];
my $def = @{ $s->[DEFS]}[$j];
my $inter;
my $lNameLen = length $lName;
if ( ref $lType) {
print HEADER <<CONTAINED_STRUCTURE;
{
SV *sv = NULL;
SV **svp = hv_fetch( $incHV, "$lName", $lNameLen, 0);
if ( !svp) {
sv = newRV_noinc(( SV*) newHV());
svp = &sv;
}
SvHV_$lType->[PROPS]->{name}( *svp, &(strucRef-> $lName), errorAt);
if ( sv)
sv_free( sv);
}
CONTAINED_STRUCTURE
} else {
print HEADER "\t$incSV = hv_fetch( $incHV, \"$lName\", $lNameLen, 0);\n";
if ($def =~ /^undef:(.*)$/) {
print HEADER "\tstrucRef-> undef.$lName = ($incSV == NULL);\n";
$def = $1;
}
if ( $lType eq 'string') {
print HEADER "\tstrucRef->is_utf8.$lName = ($incSV && prima_is_utf8_sv(*$incSV)) ? 1 : 0;\n";
}
$inter = "$incSV ? " . sv2type( $lType, "*$incSV") . " : $def";
print HEADER "\t", cwrite( $lType, $inter, "strucRef-> $lName"), "\n\n";
}
}
print HEADER "\treturn strucRef;\n";
print HEADER "}\n\n";
print HEADER "SV * sv_${_}2HV( $_ * strucRef)\n{\t\n";
print HEADER "\tHV * $incHV = newHV();\n";
for ( my $k = 0; $k < @{ $s->[TYPES]}; $k++)
{
my $lName = @{$s->[IDS]}[$k];
my $lNameLen = length $lName;
my $lType = @{$s->[TYPES]}[$k];
my $inter = type2sv( $lType, "strucRef->$lName");
my $prefix =
($s->[DEFS]->[$k] =~ /^undef:/) ?
"if (!strucRef->undef.$lName)" :
"";
print HEADER "\t$prefix (void) hv_store( $incHV, \"$lName\", $lNameLen, $inter, 0);\n";
}
print HEADER "\treturn newRV_noinc(( SV*) $incHV);\n";
print HEADER "}\n\n";
}
}
if ( $genObject)
{
out_method_profile( \@newMethods, '${ownCType}_${id}_REDEFINED', 0, 1);
out_method_profile( \@portableImports, '${ownCType}_${id}', 1, 1);
# constructor & destructor
print HEADER "\n";
print HEADER "/* patches */\n";
print HEADER "extern ${baseCType}_vmt ${baseCType}Vmt;\n" if ( $baseClass && !$genDyna);
print HEADER "extern ${ownCType}_vmt ${ownCType}Vmt;\n\n";
print HEADER "static VmtPatch ${ownCType}VmtPatch[] =\n"; # patches
print HEADER "{";
for (my $j = 0; $j <= $#newMethods; $j++)
{
my @locp = split (" ", $newMethods[ $j]);
my $id = $locp[0];
if ( $j) { print HEADER ','} ;
print HEADER "\n\t{ &(${ownCType}Vmt. $id), (void*)${ownCType}_${id}_REDEFINED, \"$id\"}";
}
print HEADER "\n\t{NULL,NULL,NULL} /* M\$C empty struct error */" unless scalar @newMethods;
print HEADER "\n};\n\n";
my $lpCount = $#newMethods + 1;
print HEADER <<LABEL;
/* Class virtual methods table */
${ownCType}_vmt ${ownCType}Vmt = {
\"${ownOClass}\",
${\($baseClass && !$genDyna ? "\&${baseCType}Vmt" : "NULL")},
${\($baseClass && !$genDyna ? "\&${baseCType}Vmt" : "NULL")},
sizeof( $ownCType ),
${ownCType}VmtPatch,
$lpCount,
( run in 0.232 second using v1.01-cache-2.11-cpan-0d8aa00de5b )