232 lines
4.2 KiB
Perl
232 lines
4.2 KiB
Perl
# Convert a C++ class file into a C header file
|
|
#
|
|
# makes alot of assumptions about the layout of the C++ file
|
|
#
|
|
|
|
while(<STDIN>) {
|
|
|
|
# 'class' <class_name> [: ['public'] <super_class_name> ] '{'
|
|
#
|
|
if(/^\s*class\s+(\w+)\s*(:\s*(public)?\s*(\w*))?\s*{/) {
|
|
$class = $1;
|
|
$super = $4;
|
|
# print "Class '$1' super='$4'\n";
|
|
|
|
push(@classes,$class);
|
|
|
|
# Construct class macro name
|
|
#
|
|
|
|
# Build macro name
|
|
#
|
|
@class_words = split("_",$class);
|
|
|
|
# See if first word of class name is some generic prefix
|
|
# and drop it if so
|
|
#
|
|
if($class_words[0] eq "br" || $class_words[0] eq "brp") {
|
|
shift(@class_words);
|
|
}
|
|
|
|
$macro_name = "";
|
|
foreach $w (@class_words) {
|
|
$macro_name .= "\u$w";
|
|
}
|
|
|
|
$class_macro_names{$class} = $macro_name;
|
|
|
|
# Initialise methods list from superclass
|
|
#
|
|
@this_methods = split(" ",$class_methods{$super});
|
|
|
|
# Read class definition
|
|
#
|
|
while(<STDIN>) {
|
|
last if(/^\s*}/);
|
|
|
|
# 'virtual' <return type> 'BR_METHOD' <name> '(' <args> [= 0] [';']
|
|
#
|
|
if(/^\s*virtual\s+(.*)\s+BR_METHOD\s+(\w+)\s*\(([^;=]*)\s*(=\s*0)?\s*(;)?\s*$/) {
|
|
|
|
$method = "$class\:\:$2";
|
|
$args = $3;
|
|
|
|
push(@this_methods,$method);
|
|
|
|
$method_return{$method} = $1;
|
|
|
|
# Read any remaining argument lines until a terminating semicolon is found
|
|
#
|
|
if(!$5) {
|
|
while(<STDIN>) {
|
|
if(/\s*([^;=]*)\s*(=\s*0)?\s*(;?)/) {
|
|
$args .= $1;
|
|
|
|
last if($3);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Tidy up argument list:
|
|
# squeeze out white space
|
|
# remove trailing ')'
|
|
# change '&' to '*' (references to pointers)
|
|
# change 'class' to 'struct'
|
|
# remove any leading and trailing space
|
|
#
|
|
$args =~ tr/\n\t \r/ /s;
|
|
$args =~ s/\)\s*$//;
|
|
$args =~ s/\&/\*/;
|
|
$args =~ s/^\s*(.*)\s*/\1/;
|
|
|
|
$method_args{$method} = $args if($args ne "void");
|
|
|
|
# print " method[$method] args[$method_args{$method}] ret[$method_return{$method}]\n";
|
|
}
|
|
|
|
# Any line with CG_PUBLIC in it gets added to front of class
|
|
#
|
|
if(/CG_PUBLIC/) {
|
|
s/CG_PUBLIC//g;
|
|
|
|
$class_public{$class} .= $_;
|
|
}
|
|
}
|
|
|
|
# Remember class list
|
|
#
|
|
$class_methods{$class} = join(" ",@this_methods);
|
|
|
|
}
|
|
}
|
|
|
|
# Start building output file
|
|
#
|
|
|
|
print <<END;
|
|
|
|
/*
|
|
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
|
|
*
|
|
* Automatically generated by classgen.pl
|
|
*/
|
|
#ifndef _\U$ARGV[0]\E_H_
|
|
#define _\U$ARGV[0]\E_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define class struct
|
|
|
|
END
|
|
|
|
# Class declarations
|
|
#
|
|
foreach $class (@classes) {
|
|
print "struct $class;\n";
|
|
}
|
|
print "\n\n";
|
|
|
|
# Classes
|
|
#
|
|
foreach $class (@classes) {
|
|
@this_methods = split(" ",$class_methods{$class});
|
|
|
|
print <<END;
|
|
struct ${class}_dispatch;
|
|
|
|
#ifndef \U${class}\E_PRIVATE
|
|
typedef struct $class {
|
|
struct ${class}_dispatch *dispatch;
|
|
$class_public{$class}
|
|
} $class;
|
|
#endif
|
|
|
|
struct ${class}_dispatch {
|
|
|
|
END
|
|
|
|
foreach $method (@this_methods) {
|
|
$ret = $method_return{$method};
|
|
$args = $method_args{$method};
|
|
|
|
($m_class, $m_name) = split("::",$method);
|
|
|
|
# Generate vtbl entry
|
|
#
|
|
print "\t$ret BR_CMETHOD_PTR_DECL($m_class, $m_name)(\n";
|
|
|
|
print "\t\tstruct $m_class *self";
|
|
|
|
foreach $arg (split(",",$args)) {
|
|
$arg =~ s/^\s*(.*)\s*/\1/;
|
|
print ",\n\t\t$arg";
|
|
}
|
|
|
|
print ");\n";
|
|
|
|
}
|
|
|
|
print "};\n";
|
|
};
|
|
|
|
# Generate C macros for calling methods
|
|
#
|
|
foreach $method (sort(keys(%method_return))) {
|
|
@args = split(",",$method_args{$method});
|
|
($m_class, $m_name) = split("::",$method);
|
|
|
|
# Construct comma seperated list of arguments for macro
|
|
#
|
|
$alist = "";
|
|
foreach $a ((1 .. @args)) {
|
|
$alist .= ", a$a";
|
|
}
|
|
|
|
$define_name = "$class_macro_names{$m_class}\u$m_name";
|
|
|
|
print "#define $define_name(self$alist) BR_CMETHOD_CALL($m_class,$m_name,self)(($m_class *)self$alist)\n";
|
|
}
|
|
|
|
# Generate templates for dispatch tables
|
|
#
|
|
|
|
print <<END;
|
|
/*
|
|
* Example templates for class dispatch tables
|
|
*/
|
|
#if 0
|
|
END
|
|
|
|
foreach $class (@classes) {
|
|
@this_methods = split(" ",$class_methods{$class});
|
|
|
|
print <<END;
|
|
/*
|
|
* Example dispatch table for $class
|
|
*/
|
|
static struct ${class}_dispatch \l$class_macro_names{$class}Dispatch = {
|
|
END
|
|
|
|
foreach $method (split(" ",$class_methods{$class})) {
|
|
($m_class, $m_name) = split("::",$method);
|
|
|
|
printf("\tBR_CMETHOD_REF(%-32s %s),\n", $m_class . "," , $m_name);
|
|
}
|
|
|
|
print "};\n\n";
|
|
|
|
}
|
|
|
|
print <<END;
|
|
#endif
|
|
|
|
#undef class
|
|
|
|
#ifdef __cplusplus
|
|
};
|
|
#endif
|
|
#endif
|
|
END
|
|
|