#!/usr/bin/tks
// ---- file : ying.tks
// ---- author : (c) 2004-2008 by Bastian Spiegel <bs@tkscript.de>
// ---- info : YInG is the YAC Interface Generator.
// ---- YAC adds a portable (and VM independent) c++ object component model with reflectance
// ----- support to the C++ language.
// ----
// ---- license: distributed under terms of the GNU General Public License.
// ----
// ---- changed: 9-Feb-2004, 13-Feb-2004, 16-Feb-2004, 17-Feb-2004, 19-Feb-2004, 21-Feb-2004
// ---- 23-Feb-2004, 5-Mar-2004, 23-Mar-2004, 19-Sep-2004, 9-Jan-2005, 11-Jan-2005
// ---- 17-Jan-2005, 5-Feb-2005, 14-Feb-2005, 10-Mar-2005 25-Apr-2005, 25-May-2005
// ---- 25-Jun-2005, 14-Jan-2006, 03-Feb-2006, 11-Nov-2007, 29-Dec-2007, 30-Jan-2008
// ---- 04-Feb-2008, 11-Feb-2008, 13-Mar-2008, 09-May-2008
// ----
// ----
module Main;
//String s_srcfile="test.h";
boolean b_group = true;
boolean b_clid = true;
boolean b_verbose = false;
boolean b_allowintfloatmixup = false; // only works when cdecl (i.e. when all args are passed on the stack)
// Last seen line#
int line_nr;
String s_srcfile;
function ParseError(String _msg) {
die("[---] YInG: "+s_srcfile+"("+line_nr+"): "+_msg+"\n");
}
function IP(String _msg) {
trace "[...] YInG: "+_msg;
}
class YGroup
{
public String name;
public String source_h; // extern sUI clid_xxx; class xxx;
public String source_cpp_templates; // templates
public String source_cpp_yac_init_cl; // register classes
public String source_cpp_yac_init_fun; // register functions
public String source_cpp_yac_exit; // YAC_Exit_<group> inner statements
public String source_cpp_fun_wrappers; // function wrappers
public method appendSources(
String _h, String _cpp_templ, String _cpp_init_cl, String _cpp_init_fun, String _cpp_exit, String _fun_wrap)
{
source_h .append(_h);
source_cpp_templates .append(_cpp_templ);
source_cpp_yac_init_cl .append(_cpp_init_cl);
source_cpp_yac_init_fun .append(_cpp_init_fun);
source_cpp_yac_exit .append(_cpp_exit);
source_cpp_fun_wrappers .append(_fun_wrap);
}
public method writeGroupFiles() {
String s_cpp;
String s_h;
s_cpp.alloc(16*1024); s_cpp.empty();
s_cpp.append("// ---- auto generated by YInG - the YAC interface generator ("+
getCurrentDateString()+" "+getCurrentTimeString()+")\n");
s_cpp.append("#ifndef __YAC__"+name+"_h__\n#define __YAC__"+name+"_h__\n\n");
s_cpp.append(source_cpp_templates);
s_cpp.append("\nvoid YAC_CALL YAC_Init_"+name+"(YAC_Host *_host) {\n\t// --------------------------------- classes ---------------------------------\n");
s_cpp.append(source_cpp_yac_init_cl);
s_cpp.append("\t// -------------------------------- functions --------------------------------\n");
s_cpp.append(source_cpp_yac_init_fun);
s_cpp.append("\n");
s_cpp.append("}\n");
s_cpp.append(source_cpp_fun_wrappers);
s_cpp.append("\nvoid YAC_CALL YAC_Exit_"+name+"(YAC_Host *_host) {\n");
s_cpp.append(source_cpp_yac_exit);
s_cpp.append("}\n");
s_cpp.append("\n#endif\n");
s_h.alloc(16*1024); s_h.empty();
s_h.append("// ---- ying_"+name+".h: auto generated by YInG - the YAC interface generator ("+
getCurrentDateString()+" "+getCurrentTimeString()+")\n");
s_h.append(source_h);
s_cpp .saveLocal("ying_"+name+".cpp");
s_h .saveLocal("ying_"+name+".h");
}
}
HashTable groups;
String s_group;
YGroup cgroup;
function AddGroup() // name=s_group
{
if(!groups.exists(s_group))
{
cgroup<=new YGroup();
cgroup.name=s_group;
groups[s_group]=deref cgroup;
}
else
{
cgroup<=groups[s_group];
}
}
int b_method_defreturn;
HashTable scanned_classes<=new HashTable;
YClass c_class;
String s_class;
YMethod c_method;
HashTable classes; classes.alloc(512);
String ordered_classes[512];
YFunction functions[512];
String yclass_typenames[]<=["YAC_Template ", "YAC_STemplate", "YAC_RTemplate"];
function UnMangle(String _s) {
if(_s.startsWith("_yac_"))
{
_s.substring(5, _s.length-5);
}
else if(_s[0]=='_')
{
_s.substring(1, _s.length-1);
}
}
function UnMangleR(String _s) {
if(scanned_classes.exists(_s))
{
return classes[_s].scriptname;
}
if(_s[0]=='_')
{
String r;
_s.substring(1, _s.length-1) => r;
return r;
}
else
{
return _s;
}
}
if(Arguments.numElements<1)
{
print "Usage: ./ying.tks [-ng,--nogroup] [-nc,--noclid] inputfile.[cpp|h]";
print " ";
print " -ng,--nogroup : Omit group header/cpp file output";
print " -nc,--noclid : Omit YAC_C(<name>); statements, usually only ";
print " for static class ID setups. (e.g. the TKS core API)";
print " -v, --verbose : Print parsed classes and methods to stdout.";
print "";
die("no input files.");
}
int total_num_functions=0;
int total_num_classes=0;
int total_num_methods=0;
int total_num_files=0;
StringArray inputfiles;
String ca;
foreach ca in Arguments
{
switch(ca)
{
case "-ng":
case "--nogroup":
b_group=false;
break;
case "-nc":
case "--noclid":
b_clid=false;
break;
case "-v":
case "--verbose":
b_verbose=true;
break;
default:
inputfiles.add(ca);
break;
}
}
dtrace b_verbose;
enum {
YCLASS_DYNAMIC =0,
YCLASS_STATIC =1,
YCLASS_RESTRICTED=2
};
function PadSpacesUntilColumn(String _s, int _col) {
int l=_col-_s.length;
loop(l) _s.append(" ");
}
function getCurrentDateString() {
Time t; t.now();
return
((["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"])[t.weekday])+", "+t.monthday+"/"+
((["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"])[t.month])+"/"+t.year;
}
function getCurrentTimeString() {
Time t;
Integer io_h;
Integer io_m;
Integer io_s;
t.now();
io_h.value=t.hour;
io_m.value=t.min;
io_s.value=t.sec;
return io_h.printf("%02i")+":"+io_m.printf("%02i")+":"+io_s.printf("%02i");
}
class YConst {
int type;
String name;
String expr;
}
int i_arginitcount;
int b_argvret;
class YArg {
int type; // 0,1,2,3
String otype; // YAC_String/YAC_ListNode/YAC_TreeNode/YAC_IntArray/YAC_FloatArray/_MyClass
String stype; // String/ListNode/TreeNode/IntArray/FloatArray/MyClass
int isarray;
getOrigArg() {
switch(type)
{
case 0:
case 1:
case 2:
return "";
case 3:
switch(otype)
{
default:
return "("+otype+"*)";
case "":
return ""; // YAC_Object*
case "YAC_String":
return "(YAC_String*)";
case "YAC_Event":
return "(YAC_Event*)";
case "YAC_ListNode":
return "(YAC_ListNode*)";
case "YAC_TreeNode":
return "(YAC_TreeNode*)";
case "YAC_Value":
return "(YAC_Value*)";
case "YAC_IntArray":
return "(YAC_IntArray*)";
case "YAC_FloatArray":
return "(YAC_FloatArray*)";
}
return "";
}
}
init(String _s) {
String tcl;
isarray=false;
otype="";
_s.trim(); // "mangled" name, e.g. "_Pixmap"
_s.replace("*","");
tcl=_s; UnMangle(tcl); //tcl.replace("_",""); // unmangled name ("Pixmap")
switch(_s) {
case 0:
case "":
case "void":
type=0;
return 1;
case "int":
case "sSI":
case "sBool":
case "sUI":
case "sS32":
//case "sS64":
type=1;
i_arginitcount++;
return 1;
case "float":
//case "double":
case "sF32":
//case "sF64":
type=2;
i_arginitcount++;
return 1;
case "YAC_Object":
type=3;
i_arginitcount++;
return 1;
case "YAC_String":
type=3; otype=_s; i_arginitcount++; stype="String";
return 1;
case "YAC_ValueObject":
type=3; otype=_s; i_arginitcount++; stype="Value";
return 1;
case "YAC_ListNode":
type=3; otype=_s; i_arginitcount++; stype="ListNode";
return 1;
case "YAC_TreeNode":
type=3; otype=_s; i_arginitcount++; stype="TreeNode";
return 1;
case "YAC_IntArray":
type=3; otype=_s; i_arginitcount++; stype="IntArray";
return 1;
case "YAC_FloatArray":
type=3; otype=_s; i_arginitcount++; stype="FloatArray";
return 1;
case "YAC_Event":
type=3; otype=_s; i_arginitcount++; stype="Event";
return 1;
case "YAC_Value":
b_argvret=true;
return 1;
case "*":
return 1;
default:
if(!scanned_classes.exists(tcl))
{
ParseError("cannot handle non-interface class \""+tcl+"\".");
}
type=3; otype=_s; stype=tcl;
i_arginitcount++;
return 1;
}
}
implement(String _arg) {
String r;
switch(type)
{
default:
case 0:
case 1:
case 2:
return "";
case 3:
switch(otype)
{
default:
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", clid_"+UnMangleR(otype)+"))";
case "":
return "";
case "YAC_String":
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", YAC_CLID_STRING))";
case "YAC_Value":
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", YAC_CLID_VALUE))";
case "YAC_ListNode":
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", YAC_CLID_LISTNODE))\n";
case "YAC_TreeNode":
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", YAC_CLID_TREENODE))";
case "YAC_IntArray":
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", YAC_CLID_INTARRAY))";
case "YAC_FloatArray":
b_method_defreturn=true;
return "if(YAC_BCHK("+_arg+", YAC_CLID_FLOATARRAY))";
}
}
}
getParam() {
switch(type)
{
default:
case 0: return "";
case 1: return "sSI";
case 2: return "sF32";
case 3: return "YAC_Object *";
}
}
getParam2() {
switch(type)
{
default:
case 0: ParseError("getParam2: cannot handle type="+type+".");
case 1: return "si";
case 2: return "f4";
case 3: return "o";
}
}
}
class YProperty : YArg {
String name;
//int type;
getTypeString() {
switch(type)
{
default:
case 0:
ParseError("YProperty::getTypeString: <void>");
break;
case 1:
return "sSI";
case 2:
return "sF32";
case 3:
return "YAC_Object *";
}
}
implementGet2();
implementSet2() {
String r;
String s_prop=name;
s_prop[0]=ucchar(s_prop[0]);
r="void YAC_CALL "+c_class.scriptname+"__set"+s_prop;
PadSpacesUntilColumn(r, 37);
r.append("(void *_o, yacmemptr _args");
PadSpacesUntilColumn(r, 78);
r.append(") {");
switch(type)
{
case 0:
ParseError("[---] YProperty::implementSet: type==void.");
case 1: // int
r.append("(("+c_class.name+"*)_o)->"+name+"=_args.mem[0].si;");
break;
case 2: // float
r.append("(("+c_class.name+"*)_o)->"+name+"=_args.mem[0].f4;");
break;
case 3: // Object
r.append("if((("+c_class.name+"*)_o)->"+name+")(("+c_class.name+"*)_o)->"+name+"->yacOperatorAssign(_args.mem[0].o);");
break;
}
r.append("}\n");
return r;
}
}
class YFunction {
String name; // original C/C++ name, e.g. _Delete
String mangled_name; // original C/C++ name or name of wrapper function (required for variable return type functions)
String script_name; // unmangled name, e.g. "Delete"
YArg return_type;
int return_new;
YArg args[];
YFunction() { return_type.type=0; args.alloc(16); }
getNumArgs() {
int r=0;
YArg a; foreach a in args
r+=(a.type!=0);
return r;
}
needWrapper() {
if(b_allowintfloatmixup)
{
// Note: Always wrap the function to be compatible with e.g. the fastcall calling convention (e.g. x86-64)
// Mixing sUI/sF32 will not work when arguments are passed in registers!
if(return_type.type==4)
return true; // return values are placed in an additional argument (YAC_Value *_r)
else
{
// ---- need wrapper method ? (return value) ----
// ---- or can we directly call the method (void method(int|float..))
int r=0;
YArg a; foreach a in args {
r=r||((a.type>2)&&(!a.otype.isBlank()));
}
return r;
}
}
else
{
return (return_type.type > 3) || (args.numElements > 0); // Wrap if arguments (fastcall!) or variable return type is used
}
}
/*virtual*/ getWrapperDecl(); // ----
/*virtual*/ implementWrapper(); // ---- global function
appendRegister(String _s);
appendRegisterArgType(String _s);
appendRegisterArgOType(String _s);
}
class YMethod : YFunction {
getWrapperDecl();
implementWrapper();
}
class YClass {
int type; // 'D' 'R' 'S'
String name;
String scriptname;
HashTable methods;
HashTable properties;
YConst constants[];
String ordered_methods[];
String ordered_properties[];
boolean b_pooled;
//String mangled_name;
YClass() {
methods.alloc(512);
properties.alloc(512);
ordered_methods.alloc(512);
ordered_properties.alloc(512);
constants.alloc(8192);
b_pooled = false;
}
}
YFunction::appendRegisterArgType {
String s="\tstatic const sUI "+mangled_name+"_arg_types";
PadSpacesUntilColumn(s, 64);
s.append("[]={");
if(args.numElements)
{
YArg a;
int b_addsep=false;
foreach a in args {
if(b_addsep)
s.append(", ");
else
b_addsep=true;
s.append(String(a.type));
}
s.append(",};\n");
}
else
s.append("0,};\n");
_s.append(s);
}
YFunction::appendRegisterArgOType {
String s="\tstatic const char *"+mangled_name+"_arg_otypes";
PadSpacesUntilColumn(s, 64);
s.append("[]={");
if(args.numElements)
{
int b_addsep=false;
YArg a;
foreach a in args {
if(b_addsep)
s.append(", ");
else
b_addsep=true;
s.append("\""+a.otype+"\"");
}
s.append(",};\n");
}
else
s.append("0,};\n");
_s.append(s);
}
YFunction::appendRegister {
int i_callstyle;
if(needWrapper())
{
// Parameters are passed through a yacmemptr that is decoded by a wrapper function
if(return_type.type==4)
i_callstyle=(args.numElements==0)+4;
else
i_callstyle=return_type.type;
}
else
{
// Parameters are directly passed to the native function
int combi = 0; // int,float/ptr arg comb. bit set == ptr (64bit on 64bit systems)
int argi = 0;
loop(args.numElements)
{
YArg arg <= args[argi];
if(arg.type > 2)
{
// Object pointers possibly require 64bit
combi |= (1<<argi);
}
argi++;
}
////i_callstyle = 8+(4*args.numElements)+return_type.type;
i_callstyle = 8 + (4*combi) + return_type.type;
argi = 0;
loop(args.numElements)
{
i_callstyle += (1<<argi) *4;
argi++;
}
}
_s.append("\t_host->yacRegisterFunction((void*)"+mangled_name
+", \""+script_name+"\", "
+return_type.type
+", \""+return_type.otype+"\", "
+args.numElements
+", "+mangled_name+"_arg_types, "+mangled_name+"_arg_otypes, "+i_callstyle+");\n");
}
YFunction::getWrapperDecl {
if(needWrapper())
{
String r; r.alloc(1024);
switch(return_type.type)
{
case 0: r="YAC_APIC void "; break;
case 1: r="YAC_APIC sSI "; break;
case 2: r="YAC_APIC sF32 "; break;
case 3: r="YAC_APIC void*"; break;
case 4: r="YAC_APIC void "; break;
}
r.append(" YAC_CALL ");
r.append(mangled_name);
PadSpacesUntilColumn(r, 37);
r.append("(");
if(args.numElements)
{
r.append("yacmemptr");
if(return_type.type==4)
r.append(", YAC_Value *");
}
else
if(return_type.type==4)
r.append("YAC_Value *");
PadSpacesUntilColumn(r, 68);
return r+");\n";
}
else
return "";
}
YMethod::getWrapperDecl {
String r; r.alloc(1024);
switch(return_type.type)
{
case 0: r="void "; break;
case 1: r="sSI "; break;
case 2: r="sF32 "; break;
case 3: r="void*"; break;
case 4: r="void "; break;
}
r.append(" YAC_CALL ");
r.append(c_class.scriptname+"__"+name);
PadSpacesUntilColumn(r, 37);
r.append("(void *");
if(args.numElements)
r.append(", yacmemptr");
if(return_type.type==4)
r.append(", YAC_Value *");
PadSpacesUntilColumn(r, 68);
return r+");\n";
}
YFunction::implementWrapper() {
if(needWrapper())
{
//trace "YFunction::implementWrapper";
String r; r.alloc(1024);
String arglist="";
switch(return_type.type)
{
case 0: r="void "; break;
case 1: r="sSI "; break;
case 2: r="sF32 "; break;
case 3: r="void*"; break;
case 4: r="void "; break;
}
r.append(" YAC_CALL ");
r.append(mangled_name);
PadSpacesUntilColumn(r, 37);
r.append("(");
int i_arg=0;
int b_addsep=false;
YArg a;
foreach a in args
{
if(a.type)
{
if(b_addsep)
arglist.append(", ");
else
{
r.append("yacmemptr _args");
b_addsep=true;
}
////arglist.append(a.getOrigArg()+"_args."+a.getParam2()+"["+i_arg+"]");
arglist.append(a.getOrigArg()+"_args.mem"+"["+i_arg+"]."+a.getParam2());
i_arg++;
}
}
if(return_type.type==4)
{
if(b_addsep)
{
r.append(", ");
arglist.append(", ");
}
r.append("YAC_Value *_r");
arglist.append("_r");
}
PadSpacesUntilColumn(r, 78);
r.append(") {");
b_method_defreturn=false;
// ---- decode parameters ----
i_arg=0;
foreach a in args
{
if(a.type)
{
////r.append(a.implement("_args."+a.getParam2()+"["+i_arg+"]"));
r.append(a.implement("_args.mem"+"["+i_arg+"]."+a.getParam2()));
i_arg++;
}
}
if(b_method_defreturn) r.append("{ ");
// ---- call wrapped method ----
switch(return_type.type)
{
case 1: r.append("return (sSI)"); break;
case 2: r.append("return (sF32)"); break;
case 3: r.append("return (void*)"); break;
}
r.append(name+"("+arglist+");");
if(b_method_defreturn) {
r.append("}");
switch(return_type.type)
{
case 1:
r.append("return 0;");
break;
case 2:
r.append("return 0.0f;");
break;
case 3:
r.append("return (void*)0;");
break;
}
}
return r+"}\n";
}
else
{
return "";
}
}
YMethod::implementWrapper() {
String r; r.alloc(1024);
String arglist="";
switch(return_type.type)
{
case 0: r="void "; break;
case 1: r="sSI "; break;
case 2: r="sF32 "; break;
case 3: r="void*"; break;
case 4: r="void "; break;
}
r.append(" YAC_CALL ");
r.append(c_class.scriptname+"__"+name);
PadSpacesUntilColumn(r, 37);
r.append("(void *_o");
int i_arg=0;
int b_addsep=false;
YArg a;
foreach a in args
{
if(a.type)
{
if(b_addsep)
arglist.append(", ");
else
{
r.append(", yacmemptr _args");
b_addsep=true;
}
////arglist.append(a.getOrigArg()+"_args."+a.getParam2()+"["+i_arg+"]");
arglist.append(a.getOrigArg()+"_args.mem"+"["+i_arg+"]."+a.getParam2());
i_arg++;
}
}
if(return_type.type==4)
{
r.append(", YAC_Value *_r");
if(b_addsep)
arglist.append(", ");
arglist.append("_r");
}
PadSpacesUntilColumn(r, 78);
// l=78-r.length;
// if(l>0) loop(l) r.append(" ");
r.append(") {");
b_method_defreturn=false;
// ---- decode parameters ----
i_arg=0;
foreach a in args
{
if(a.type)
{
////r.append(a.implement("_args."+a.getParam2()+"["+i_arg+"]"));
r.append(a.implement("_args.mem"+"["+i_arg+"]."+a.getParam2()));
i_arg++;
}
}
if(b_method_defreturn) r.append("{ ");
// ---- call wrapped method ----
switch(return_type.type)
{
case 1: r.append("return (sSI)"); break;
case 2: r.append("return (sF32)"); break;
case 3: r.append("return (void*)"); break;
}
r.append("(("+c_class.name+"*)_o)->"+name+"("+arglist+");");
if(b_method_defreturn) {
r.append("}");
switch(return_type.type)
{
case 1:
r.append("return 0;");
break;
case 2:
r.append("return 0.0f;");
break;
case 3:
r.append("return (void*)0;");
break;
}
}
return r+"}\n";
}
function AddClass(int _type) {
trace "AddClass(\""+s_class+"\", _type="+_type+")";
c_class<=new YClass;
classes[s_class]=deref c_class;
c_class.type=_type; //YCLASS_DYNAMIC, YCLASS_STATIC, YCLASS_RESTRICTED
c_class.name=s_class;
if(s_class=="YAC_Object")
c_class.scriptname="Object";
else
{
c_class.scriptname=s_class;
UnMangle(c_class.scriptname);
}
ordered_classes.add(s_class);
total_num_classes++;
}
function AddMethod(String _name, String _return, ListNode _args) {
_name.replace("*","");
trace "AddMethod(\""+_name+"\")";
c_method<=new YMethod;
c_method.name=_name;
String s_scriptname=_name;
UnMangle(s_scriptname); //.replace("_","");
c_method.script_name=s_scriptname; // e.g. "_delete" => "delete"
//trace "c_method.script_name="+c_method.script_name;
HashTable h<=c_class.methods;
h[_name]=deref c_method;
c_class.ordered_methods.add(_name);
_return.replace("*","");
YArg c_return<=c_method.return_type;
if(!c_return.init(_return))
{
ParseError("[---] cannot handle return type \""+_return+"\"\n");
}
i_arginitcount=0;
b_argvret=false;
Value v; foreach v in _args {
//trace "AddMethod arg["+i_arginitcount+"] type="+v.type+" string="+v.string;
if(v.type)
{
if(!c_method.args[i_arginitcount].init(v.stringValue))
{
ParseError("YMethod: cannot handle argument "+i_arginitcount+" type \""+v.stringValue+"\".");
}
}
}
if(b_argvret) c_return.type=4;
c_method.args.setNumElements(i_arginitcount);
total_num_methods++;
}
function AddFunction(String _name, String _return, ListNode _args) {
trace "AddFunction(name=\""+_name+"\", return=\""+_return+"\" args="+_args+")";
total_num_functions++;
_name.replace("*","");
YFunction f<=functions.nextFree;
f.name=_name;
f.script_name = _name;
UnMangle(f.script_name);
_return.replace("*","");
YArg f_return<=f.return_type;
if(!f_return.init(_return))
{
ParseError("YFunction: cannot handle return type \""+_return+"\"");
}
i_arginitcount=0;
b_argvret=false;
Value v; foreach v in _args {
//trace "AddFunction arg["+i_arginitcount+"] type="+v.type+" string="+v.string;
if(v.type)
{
if(!f.args[i_arginitcount].init(v.stringValue))
{
ParseError("YFunction: cannot handle argument "+i_arginitcount+" type \""+v.stringValue+"\".");
}
}
}
f.args.setNumElements(i_arginitcount);
if(b_argvret) f_return.type=4;
if(f.needWrapper())
f.mangled_name="__APIC__"+_name;
else
f.mangled_name=_name;
}
function AddProperty(String _name, String _type) {
HashTable h<=c_class.properties;
_name.replace("*", "");
_name.trim();
YProperty p<=new YProperty();
h[_name]=deref p;
c_class.ordered_properties.add(_name);
p.name=_name;
if(!p.init(_type))
{
ParseError("cannot handle property type \""+_type+"\".");
}
}
function AddConstant(String _name, String _expr, int _type) {
// trace "AddConstant(name=\""+_name+"\" expr=\""+_expr+"\" type="+_type+")";
YConst c<=c_class.constants.nextFree;
//trace "c="+c;
UnMangle(_name); //_name.replace("_","");
c.name=_name;
c.type=_type;
c.expr=_expr;
}
String s_cpp_templ, s_cpp_init_cl, s_cpp_init_fun, s_cpp_exit, s_cpp_funwrap;
// String s_h;
String s_group_h;
function CPPOut() {
String s_clid_def="";
String tcl;
String s_classfdecl="";
s_cpp_templ .alloc(8*1024); s_cpp_templ .empty();
s_cpp_init_cl .alloc(8*1024); s_cpp_init_cl .empty();
s_cpp_init_fun.alloc(8*1024); s_cpp_init_fun.empty();
s_cpp_exit .alloc(4*1024); s_cpp_exit .empty();
s_cpp_funwrap .alloc(4*1024); s_cpp_funwrap .empty();
// s_cpp.append("// ---- auto generated by YInG - the YAC interface generator ("+
// getCurrentDateString()+" "+getCurrentTimeString()+")\n");
// s_cpp.append("#ifndef __YAC__"+s_group+"_h__\n#define __YAC__"+s_group+"_h__\n\n");
s_group_h.alloc(16*1024); s_group_h.empty();
// s_group_h.append("// ---- ying_"+s_group+".h: auto generated by YInG - the YAC interface generator ("+
// getCurrentDateString()+" "+getCurrentTimeString()+")\n");
String scl;
YClass c;
foreach scl in ordered_classes {
c<=classes[scl];
c_class<=c;
tcl=c.name; //"__YAC_"+scl;
String s_cl;
// String s_decl; s_decl.alloc(4*1024); s_decl.empty();
String s_cdecl; s_cdecl.alloc(4*1024); s_cdecl.empty();
// String s_def; s_def.alloc(4*1024); s_def.empty();
String s_cdef; s_cdef.alloc(4*1024); s_cdef.empty();
s_cl.alloc(16*1024); s_cl.empty();
s_cdecl.append("// ---- ying_"+s_group+"_"+c.scriptname+".cpp: auto generated by YInG - the YAC interface generator ("+
getCurrentDateString()+" "+getCurrentTimeString()+")\n\n");
// ---- write method declarations/exports ----
s_classfdecl.append("class "+tcl+";\n");
int i_method=1;
int i_member=0;
String s_method_pfx;
String s_method;
int i_maxmethodlen=1;
foreach s_method in c.ordered_methods {
c_method<=c.methods[s_method];
if(c_method.name.length>i_maxmethodlen)
i_maxmethodlen=c_method.name.length;
}
foreach s_method in c.ordered_methods {
c_method<=c.methods[s_method];
s_cdecl.append(c_method.getWrapperDecl());
}
String s_property;
YProperty p;
String s_prop_impl; s_prop_impl.alloc(4*1024); s_prop_impl.empty();
foreach s_property in c.ordered_properties {
p<=c.properties[s_property];
String s_prop=p.name;
s_prop[0]=ucchar(s_prop[0]);
int l;
if(!c.methods.exists("get"+s_prop))
{
i_method++;
String s_get_decl;
switch(p.type)
{
case 0: s_get_decl="void "; break;
case 1: s_get_decl="sSI "; break;
case 2: s_get_decl="sF32 "; break;
case 3: s_get_decl="void*"; break;
}
s_get_decl.append(" YAC_CALL ");
s_get_decl.append(tcl+"__get"+s_prop);
PadSpacesUntilColumn(s_get_decl, 37);
s_get_decl.append("(void *");
PadSpacesUntilColumn(s_get_decl, 68);
s_cdecl.append(s_get_decl+");\n");
// ---- implement property get method ----
s_prop_impl.append(p.implementGet2());
}
if(!c.methods.exists("set"+s_prop))
{
i_method++;
String s_set_decl="void YAC_CALL "+tcl+"__set"+s_prop;
PadSpacesUntilColumn(s_set_decl, 37);
s_set_decl.append("(void *, yacmemptr");
PadSpacesUntilColumn(s_set_decl, 68);
s_cdecl.append(s_set_decl+");\n");
// ---- implement property set method ----
s_prop_impl.append(p.implementSet2());
}
i_member++;
}
if(b_clid)
{
if(c.b_pooled)
{
s_cdef.append("YAC_C_POOLED("+tcl+", \""+c.scriptname+"\");\n\n");
}
else
{
s_cdef.append("YAC_C("+tcl+", \""+c.scriptname+"\");\n\n");
}
}
s_group_h.append("extern sUI clid_"+c.scriptname+";\n");
s_cpp_templ.append("sUI clid_"+c.scriptname+";\n");
String s_template=yclass_typenames[c.type]+"<"+tcl+">";
PadSpacesUntilColumn(s_template, 48);
s_cpp_templ.append(s_template+"*t_"+c.scriptname+";\n");
s_cl.append("// ------------------ YAC class \""+tcl+"\" reflection map (implementation) ------------------\n");
if(i_member)
{
String s_cl_member_name="";
String s_cl_member_type="";
String s_cl_member_objecttype="";
String s_cl_member_offset="";
int b_addsep=false;
foreach s_property in c.ordered_properties {
p<=c.properties[s_property];
if(b_addsep)
{
s_cl_member_name.append(", ");
s_cl_member_type.append(", ");
s_cl_member_objecttype.append(", ");
s_cl_member_offset.append(", ");
}
else b_addsep=true;
s_cl_member_name.append("\""+p.name+"\"");
s_cl_member_type.append(String(p.type));
if(!p.stype.isBlank())
s_cl_member_objecttype.append("\""+p.stype+"\"");
else
s_cl_member_objecttype.append("(const char*)0");
//s_cl_member_offset.append("(((sSI)&"+p.name+")-((sSI)this))");
s_cl_member_offset.append("((sU8*)((((sU8*)&"+p.name+")-((sU8*)this))))");
}
s_cl.append("sUI YAC_VCALL "+tcl+"::yacMemberGetNum (void) {return "+i_member+";}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMemberGetNames (void) {static const char*r[]={"+s_cl_member_name+"};return r; }\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacMemberGetTypes (void) {static const sUI r[]={"+s_cl_member_type+"}; return r; }\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMemberGetObjectTypes (void) {static const char*r[]={"+s_cl_member_objecttype+"};return r; }\n");
s_cl.append("const sU8 **YAC_VCALL "+tcl+"::yacMemberGetOffsets (void) {static const sU8*r[]={"+s_cl_member_offset+"};return r;}\n");
}
else
{
s_cl.append("sUI YAC_VCALL "+tcl+"::yacMemberGetNum (void) {return 0;}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMemberGetNames (void) {return 0;}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacMemberGetTypes (void) {return 0;}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMemberGetObjectTypes (void) {return 0;}\n");
s_cl.append("const sU8 **YAC_VCALL "+tcl+"::yacMemberGetOffsets (void) {return (const sU8**)0;}\n");
}
if(i_method||c.ordered_methods.numElements)
{
String s_cl_method_name="\"operator\"";
String s_cl_method_numparam="2";
String s_cl_method_param_types="";
String s_cl_method_param_typesd="";
String s_cl_method_param_otypes="";
String s_cl_method_param_otypesd="";
String s_cl_method_return_type="4";
String s_cl_method_return_otype="\"\"";
String s_cl_method_adr="(void*)Object__operator";
String s_cl_method_adr2="(void*)0";
int i_typesd=1;
s_cl_method_param_typesd.append("static const sUI rt0[]={1,3};");
s_cl_method_param_types.append("rt0");
s_cl_method_param_otypesd.append("static const char *rs0[]={0,\"\",};");
s_cl_method_param_otypes.append("rs0");
foreach s_method in c.ordered_methods {
i_method++;
c_method<=c.methods[s_method];
s_cl_method_name.append(", ");
s_cl_method_numparam.append(", ");
s_cl_method_param_types.append(", ");
s_cl_method_param_otypes.append(", ");
s_cl_method_return_type.append(", ");
s_cl_method_return_otype.append(", ");
s_cl_method_param_typesd.append("static const sUI rt"+i_typesd+"[]=");
s_cl_method_param_otypesd.append("static const char *rs"+i_typesd+"[]=");
s_cl_method_numparam.append(String(c_method.args.numElements));
s_cl_method_name.append("\""+c_method.script_name+"\"");
s_cl_method_return_type.append(String(c_method.return_type.type));
if(!c_method.return_type.stype.isBlank())
s_cl_method_return_otype.append("\""+c_method.return_type.stype+"\"");
else
s_cl_method_return_otype.append("(const char*)0");
s_cl_method_adr.append(", (void*)"+c.scriptname+"__"+c_method.name);
s_cl_method_adr2.append(", (void*)__JIT__"+c.scriptname+"__"+c_method.name);
int b_addsep3=false;
if(c_method.args.numElements)
{
s_cl_method_param_typesd.append("{");
s_cl_method_param_otypesd.append("{");
YArg a; foreach a in c_method.args {
if(b_addsep3)
{
s_cl_method_param_typesd.append(", ");
s_cl_method_param_otypesd.append(", ");
}
else
b_addsep3=true;
s_cl_method_param_typesd.append(String(a.type));
if(!a.stype.isBlank())
s_cl_method_param_otypesd.append("\""+a.stype+"\"");
else
s_cl_method_param_otypesd.append("(const char*)0");
}
s_cl_method_param_typesd.append(",};");
s_cl_method_param_otypesd.append(",};");
}
else
{
s_cl_method_param_typesd.append("{0,};");//
s_cl_method_param_otypesd.append("{(const char*)0,};");
}
s_cl_method_param_types.append("rt"+(i_typesd));
s_cl_method_param_otypes.append("rs"+(i_typesd++));
}
foreach s_property in c.ordered_properties {
p<=c.properties[s_property];
s_prop=p.name;
s_prop[0]=ucchar(s_prop[0]);
if(!c.methods.exists("get"+s_prop))
{
s_cl_method_name.append(", \"get"+s_prop+"\"");
s_cl_method_numparam.append(", 0");
s_cl_method_param_typesd.append("static const sUI rt"+i_typesd+"[]={0,};");
s_cl_method_param_otypesd.append("static const char *rs"+i_typesd+"[]={\"\", };");
s_cl_method_param_types.append(", rt"+(i_typesd));
s_cl_method_param_otypes.append(", rs"+(i_typesd++));
s_cl_method_return_type.append(", "+p.type);
s_cl_method_return_otype.append(", \""+p.stype+"\"");
s_cl_method_adr.append(", (void*)"+tcl+"__get"+s_prop);
//i_method++;
}
if(!c.methods.exists("set"+s_prop))
{
s_cl_method_name.append(", \"set"+s_prop+"\"");
s_cl_method_numparam.append(", 1");
s_cl_method_param_typesd.append("static const sUI rt"+i_typesd+"[]={"+p.type+",};");
s_cl_method_param_otypesd.append("static const char *rs"+i_typesd+"[]={\""+p.stype+"\", };");
s_cl_method_param_types.append(", rt"+(i_typesd));
s_cl_method_param_otypes.append(", rs"+(i_typesd++));
s_cl_method_return_type.append(", 0");
s_cl_method_return_otype.append(", \"\"");
s_cl_method_adr.append(", (void*)"+tcl+"__set"+s_prop);
//i_method++;
}
}
s_cl.append("sUI YAC_VCALL "+tcl+"::yacMethodGetNum (void) {return "+i_method+";}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMethodGetNames (void) {static const char *r[]={"+s_cl_method_name+"}; return r;}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacMethodGetNumParameters (void) {static const sUI r[]={"+s_cl_method_numparam+"}; return r;}\n");
s_cl.append("const sUI **YAC_VCALL "+tcl+"::yacMethodGetParameterTypes (void) {"+s_cl_method_param_typesd+"static const sUI *r[]={"+s_cl_method_param_types+"}; return r;}\n");
s_cl.append("const char***YAC_VCALL "+tcl+"::yacMethodGetParameterObjectTypes (void) {"+s_cl_method_param_otypesd+"static const char**r[]={"+s_cl_method_param_otypes+"}; return r;}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacMethodGetReturnTypes (void) {static const sUI r[]={"+s_cl_method_return_type+"}; return r;}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMethodGetReturnObjectTypes (void) {static const char *r[]={"+s_cl_method_return_otype+"}; return r;}\n");
s_cl.append("const void **YAC_VCALL "+tcl+"::yacMethodGetAdr (void) {static const void *r[]={"+s_cl_method_adr+"}; return r;}\n");
}
else
{
s_cl.append("sUI YAC_VCALL "+tcl+"::yacMethodGetNum (void) {return 1;}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMethodGetNames (void) {static const char *r[]={\"operator\",}; return r;}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacMethodGetNumParameters (void) {return {2,};\n");
s_cl.append("const sUI **YAC_VCALL "+tcl+"::yacMethodGetParameterTypes (void) {static const sUI r0[]={1,3,}; return {r0,};}\n");
s_cl.append("const char***YAC_VCALL "+tcl+"::yacMethodGetParameterObjectTypes (void) {static const char *r0[]={\"\",}; return {r0,};}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacMethodGetReturnTypes (void) {return {4,};}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacMethodGetReturnObjectTypes (void) {return {\"\",};}\n");
s_cl.append("const void **YAC_VCALL "+tcl+"::yacMethodGetAdr (void) {static const void*r[]={(void*)Object__operator,}; return r;}\n");
}
if(c.constants.numElements)
{
String s_const;
String s_const_name="";
String s_const_type="";
String s_const_value="";
b_addsep3=false;
int i_const=0;
YConst co; foreach co in c.constants {
if(b_addsep3)
{
s_const_name.append(", ");
s_const_type.append(", ");
}
else
b_addsep3=true;
s_const_name.append("\""+co.name+"\"");
s_const_type.append(String(co.type));
if(co.type==1)
s_const_value.append("m.si["+i_const+"]=(sSI)"+co.expr+";");
else
s_const_value.append("m.f4["+i_const+"]=(sF32)"+co.expr+";");
i_const++;
}
s_cl.append("sUI YAC_VCALL "+tcl+"::yacConstantGetNum (void) {return "+i_const+";}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacConstantGetNames (void) {static const char*r[]={"+s_const_name+"}; return r;}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacConstantGetTypes (void) {static const sUI r[]={"+s_const_type+"}; return r;}\n");
s_cl.append("yacmemptr YAC_VCALL "+tcl+"::yacConstantGetValues (void) {static sUI r["+i_const+"]; yacmemptr m; m.ui=r; "+s_const_value+"; return m;}\n");
}
else
{
s_cl.append("sUI YAC_VCALL "+tcl+"::yacConstantGetNum (void) {return 0;}\n");
s_cl.append("const char **YAC_VCALL "+tcl+"::yacConstantGetNames (void) {static const char*r[]={\"\"}; return r;}\n");
s_cl.append("const sUI *YAC_VCALL "+tcl+"::yacConstantGetTypes (void) {static const sUI r[]={0}; return r;}\n");
s_cl.append("yacmemptr YAC_VCALL "+tcl+"::yacConstantGetValues (void) {static sUI r[]={0,};yacmemptr m; m.ui=(sUI*)r; return m;}\n");
}
// s_h.append(s_decl+"\n");
// s_h.append(s_def);
s_cl=s_cdecl+"\n"+s_cl+"\n"+s_cdef;
// ---- implement wrapper methods ----
foreach s_method in c.ordered_methods {
c_method<=c.methods[s_method];
s_cl.append(c_method.implementWrapper());
}
s_cl.append(s_prop_impl);
s_cl.saveLocal("ying_"+s_group+"_"+c.scriptname+".cpp");
}
s_group_h.append(s_classfdecl);
s_group_h.append(s_clid_def);
// s_cpp.append("\nvoid YAC_Init_"+s_group+"(YAC_Host *_host) {\n\t// --------------------------------- classes ---------------------------------\n");
// s_cpp_init.append("\n\t// --------------------------------- classes ---------------------------------\n");
foreach scl in ordered_classes {
c<=classes[scl];
tcl=c.name;
//tcl="__YAC_"+scl;
String s_newtemp="\t t_"+c.scriptname;
PadSpacesUntilColumn(s_newtemp, 32);
s_cpp_init_cl.append(s_newtemp+"=new "+yclass_typenames[c.type]+"<"+tcl+">(_host);\n");
s_newtemp="\tclid_"+c.scriptname;
PadSpacesUntilColumn(s_newtemp, 32);
s_cpp_init_cl.append(s_newtemp+"= t_"+c.scriptname+"->ctemplate.class_ID;\n");
}
//s_cpp_init.append("\t// -------------------------------- functions --------------------------------\n$(YAC_REGISTER_FUN)}\n");
// s_cpp.append("\nvoid YAC_Exit_"+s_group+"(YAC_Host *_host) {\n");
// ---- delete in reverse order ---
int i=ordered_classes.numElements;
while(--i>=0) {
scl=ordered_classes[i];
c<=classes[scl];
s_cpp_exit.append("\tdelete t_"+c.scriptname+";\n");
}
// s_cpp.append("}\n");
// ---- process "C" function bindings ----
String s_fun="";
String s_fun_arg_types="";
String s_fun_arg_otypes="";
YFunction f;
foreach f in functions {
s_group_h.append(f.getWrapperDecl());
s_cpp_funwrap.append(f.implementWrapper());
f.appendRegister(s_fun);
f.appendRegisterArgType(s_fun_arg_types);
f.appendRegisterArgOType(s_fun_arg_otypes);
}
//s_cpp_init.replace("$(YAC_REGISTER_FUN)", s_fun_arg_types+s_fun_arg_otypes+s_fun);
s_cpp_init_fun.append(s_fun_arg_types);
s_cpp_init_fun.append(s_fun_arg_otypes);
s_cpp_init_fun.append(s_fun);
if(cgroup)
{
cgroup.appendSources(s_group_h, s_cpp_templ, s_cpp_init_cl, s_cpp_init_fun, s_cpp_exit, s_cpp_funwrap);
}
else
{
die "[---] ying: the current group has not been set. (YG(\"mygroup\");).\n";
}
// s_cpp.append("\n\n#endif\n");
// if(b_group)
// {
// s_cpp.saveLocal("ying_"+s_group+".cpp");
// s_group_h.saveLocal("ying_"+s_group+".h");
// }
trace "\n-------------------------------------\n";//+s_cpp;
}
YProperty::implementGet2() {
String r;
String s_prop=name;
s_prop[0]=ucchar(s_prop[0]);
switch(type)
{
case 0: r="void "; break;
case 1: r="sSI "; break;
case 2: r="sF32 "; break;
case 3: r="void*"; break;
}
r.append(c_class.scriptname+"__get"+s_prop);
PadSpacesUntilColumn(r, 37);
r.append("(void *_o");
PadSpacesUntilColumn(r, 78);
r.append(") {");
switch(type)
{
case 1: r.append("return (sSI)"); break;
case 2: r.append("return (sF32)"); break;
case 3: r.append("return (void*)"); break;
}
r.append("(("+c_class.name+"*)_o)->"+name+";");
r.append("}\n");
return r;
}
// ---------------------------------------------------------------------------------------------------------
function parseInterface(String s_srcfile) {
String s_in;
int found_something=false;
if(!s_in.loadLocal(s_srcfile, true))
die "[---] ying: failed to load input file \""+s_srcfile+"\".";
classes.free(); classes.alloc(512);
ordered_classes.empty();
functions.empty();
s_group="UNTITLED";
cgroup<=null;
c_class<=null;
b_method_defreturn=false;
s_in.split('\n');
String cl;
int i_cl=1;
//int b_class=false;
int i,j;
String st,st2,st3,st4;
// ---- scan classes ----
foreach cl in s_in {
int nameOff;
i = cl.indexOf("YC class",0);
if(-1 == i)
{
i = cl.indexOf("YCR class", 0);
if(-1 == i)
{
i = cl.indexOf("YCS class", 0);
nameOff = 9;
}
else
{
nameOff = 9;
}
}
else
{
nameOff = 8;
}
if(i != -1)
{
// ---- extract class name ----
cl.substring(i+nameOff, cl.length-(i+nameOff)) => st;
String tcl = st.splitSpace(0).getCopy(0);
tcl.replace(":",""); // "class MyClass: public Bla"
UnMangle(tcl); //.replace("_","");
scanned_classes[tcl]=true;
IP("scanned class \""+tcl+"\"");
}
}
line_nr = 1;
foreach cl in s_in {
ListNode l,lc;
String s_arg;
int class_type=0;
//Integer io; io.value=i_cl;
//trace "["+io.printf("%3i")+"]: "+cl;
i_cl++;
i=cl.indexOf("YG(\"",0);
if(i!=-1)
{
// ---- extract group name ----
j=cl.indexOf("\")", i+4);
if(j!=-1)
{
cl.substring(i+4, j-(i+4)) => s_group;
trace "[...] current group set to \""+s_group+"\".";
AddGroup();
}
else
die("[---] ying: error parsing YG(\"\") group name definition.");
}
else
{
i=cl.indexOf("YC class",0);
if(i==-1)
{
i=cl.indexOf("YCS class", 0);
if(i!=-1)
class_type=YCLASS_STATIC; // found "YCS class" definition
else
{
i=cl.indexOf("YCR class", 0);
if(i!=-1)
{
class_type=YCLASS_RESTRICTED; // found "YCR class" definition
}
else
{
// ---- no class?
i=cl.indexOf("class", 0);
if(i!=-1)
{
String chars_before_class;
cl.substring(0, i) => chars_before_class;
if(chars_before_class.isBlank())
{
c_class <= null;
}
}
i=-1;
}
}
}
else
{
class_type = YCLASS_DYNAMIC; // found "YC class" definition
}
if(i != -1)
{
// ---- extract class name ----
cl.replace("YAC_API","");
cl.substring(i+8+(class_type!=YCLASS_DYNAMIC), cl.length-(i+8)) => st;
s_class = st.splitSpace(1).getCopy(0);
s_class.replace(":","");
AddClass(class_type);
//b_class=true;
found_something = true;
}
else
{
cl.trim() => st;
if(st.startsWith("YAC_POOLED"))
{
if(c_class != null)
{
c_class.b_pooled = true;
}
}
else if(st.startsWith("YF "))
{
c_class<=null;
// ---- parse function ----
// YF void YAC_CALL test(void);
// YF int YAC_CALL test(void);
// YF void YAC_CALL test(int _i, int _j, int _k)
st.replace("//","");
st.words(false);
String s_yaccall = st.getWord(2);
if( (s_yaccall != "YAC_CALL") && (s_yaccall != "*YAC_CALL") )
{
ParseError("expected YAC_CALL in function export \"YF " +st.getWord(1) +" " + s_yaccall+"\".");
}
st2=st.getWord(3);
i=st2.indexOf("(", 0); // void name(void)
if(i==-1)
{
st2.append(st.getWord(4)); // void name (void)
i=st2.indexOf("(", 0);
}
st2.substring(0, i) => st3; //get name ("test")
i = st.indexOf("(", 0);
j = st.indexOf(")", 0);
st.substring(i+1, j-(i+1)) => st4; // st4=args ("void","int")
l <= new ListNode;
lc <= l;
foreach s_arg in st4.splitChar(',')
{
lc <= lc.appendValue(#(String(s_arg.splitSpace(0).getCopy(0))));
}
AddFunction(st3, st.getWord(1), l);
l <= 0;
st.freeStack();
found_something=true;
}
if
(
c_class!=null
)
{
if(st.startsWith("YM "))
{
// ---- parse method ----
// YM void test(void);
// YM int test(void);
// YM void test(int _i, int _j, int _k)
// YM YAC_ListNode * test(void)
st.replace("//","");
st.replace("YM virtual","YM ");
st.words(false);
st2=st.getWord(2);
int i_name;
if(st2=="*")
{
st2=st.getWord(3);
i_name=4;
}
else
i_name=3;
i=st2.indexOf("(", 0); // void name(void)
if(i==-1)
{
st2.append(st.getWord(i_name)); // void name (void)
i=st2.indexOf("(", 0);
}
st2.substring(0, i) => st3; //get name ("test")
i = st.indexOf("(", 0);
j = st.indexOf(")", 0);
st.substring(i+1, j-(i+1)) => st4; // st4=args ("void","int")
l <= new ListNode;
lc <= l;
if(st4.isBlank())
{
ParseError("empty argument list in method "+c_class.scriptname+"::"+st3);
}
foreach s_arg in st4.splitChar(',')
{
lc <= lc.appendValue(#(String(s_arg.splitSpace(0).getCopy(0))));
}
AddMethod(st3, st.getWord(1), l);
l<=0;
st.freeStack();
}
else
{
if(st.startsWith("YP "))
{
// ---- parse property ----
// YP sSI myint;
// YP sF32 myfloat;
//
st.replace("//","");
st.words(false);
st2=st.getWord(2);
i=st2.indexOf(";", 0);
st2.substring(0, i) => st3;
AddProperty(st3, st.getWord(1));
st.freeStack();
}
else
{
if(st.startsWith("#define")||st.startsWith("//#define"))
{
// ---- parse constant ----
// #define YCI TEST_INT_CONSTANT 42
// //#define YCI EXPORT_INT_CONSTANT 42
// #define YCF TEST_INT_CONSTANT 42.42
// //#define YCF EXPORT_INT_CONSTANT 42.42
//
st.words(false);
if(st.getWord(2)=="YCI")
AddConstant(st.getWord(1), st.getWord(3),1);
else if(st.getWord(2)=="YCF")
AddConstant(st.getWord(1), st.getWord(3),2);
st.freeStack();
}
}
}
} // c_class!=null
}
}
// Process next line
line_nr++;
} // foreach cl in s_in
s_in.freeStack();
if(found_something)
{
CPPOut();
trace "[...] found "+classes.numElements+" classes.";
trace ".";
total_num_files++;
}
}
// ---- parse all input files ----
trace "Starting to process "+inputfiles.numElements+" input file(s).";
foreach s_srcfile in inputfiles {
trace "s_srcfile="+s_srcfile;
parseInterface(s_srcfile);
}
// ---- write group .h and .cpp files
if(b_group)
{
String gkey;
foreach gkey in groups {
YGroup g<=groups[gkey];
g.writeGroupFiles();
}
}
print "Found "+total_num_functions+" functions and "+total_num_methods+" method(s) in "+total_num_classes+" class(es) in "+groups.numElements+" groups in "+total_num_files+"/"+inputfiles.numElements+" input file(s).";