diff --git a/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike b/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike index f234d18b5ef5398d59403d2a7d50f3e365398d01..c5ef827c68b9b3cb17682b9621b18f9232bcb505 100644 --- a/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike +++ b/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike @@ -19,10 +19,13 @@ constant precompile_api_version = "3"; constant want_args = 1; constant description = "Converts .pmod-files to .c files"; + +mapping map_types = ([]), need_obj_defines = ([]); + string usage = #"[options] <from> > <to> - This script is used to process *.cmod files into *.c files, it + This script is used to process *.cmod files into *.c files, it reads Pike style prototypes and converts them into C code. Supported options are: @@ -827,8 +830,12 @@ class PikeType case "longest": return "tInt"; - case "object": return "tObj"; + case "object": + return "tObj"; default: + string define = "tObjImpl_"+replace(upper_case(ret), ".", "_"); + if( !need_obj_defines[define] ) + need_obj_defines[define] = ret; return sprintf("tName(%O, tObjImpl_%s)", ret, replace(upper_case(ret), ".", "_")); } @@ -1682,6 +1689,8 @@ array generate_overload_func_for(array(FuncData) d, return out; } +int gid; + // Parses a block of cmod code, separating it into declarations, // functions to add, exit functions and other code. class ParseBlock @@ -1690,6 +1699,7 @@ class ParseBlock array addfuncs=({}); array exitfuncs=({}); array declarations=({}); + int local_id = ++gid; void create(array(array|PC.Token) x, string base, string class_name) { @@ -1881,6 +1891,9 @@ sprintf(" } else {\n" ret+=subclass->declarations; ret+=subclass->code; + need_obj_defines["tObjImpl_"+upper_case(lname)] = 1; + map_types[subclass->local_id] = ({ define, "return "+program_var+"->id;" }); + addfuncs+= IFDEF(define, ({ @@ -1898,7 +1911,10 @@ sprintf(" } else {\n" proto[0]->line), IFDEF("tObjImpl_"+upper_case(lname), 0, - DEFINE("tObjImpl_"+upper_case(lname), "tObj")), + DEFINE("tObjIs_"+upper_case(lname), + sprintf("%O",sprintf("\3\1\x7f%3c", subclass->local_id)))+ + DEFINE("tObjImpl_"+upper_case(lname), + sprintf("%O",sprintf("\3\0\x7f%3c", subclass->local_id)))), })+ subclass->addfuncs+ ({ @@ -2415,7 +2431,7 @@ static struct %s *%s_gdb_dummy_ptr; ret+=({ PC.Token(sprintf("if (args > %d &&" " (TYPEOF(Pike_sp[%d%s]) != PIKE_T_INT ||" - " Pike_sp[%d%s].u.integer)) {\n", + " Pike_sp[%d%s].u.integer)) {\n", argnum, argnum, check_argbase, argnum, check_argbase), arg->line()), @@ -2711,7 +2727,8 @@ static struct %s *%s_gdb_dummy_ptr; })); } else { addfuncs+=IFDEF(define, ({ - PC.Token(sprintf(" %s =\n", func_num)), + IFDEF(func_num+"_used", + ({PC.Token(sprintf(" %s =", func_num))})), PC.Token(sprintf(" ADD_FUNCTION2(%O, %s, %s, %s, %s);\n", attributes->name || name, funcname, @@ -2792,27 +2809,65 @@ class Handler { void create(mapping|void predefines) { ::create(); - if (predefines) this::predefines = predefines; + if (predefines) this_program::predefines = predefines; } } int find_identifier( array in, string ident ) { - foreach( in, mixed q ) + foreach( in, mixed q ) + { + if( objectp(q) ) { - if( objectp(q) ) - { - if( q == ident ) return 1; - } - else if( arrayp( q ) ) - { - if( find_identifier( q, ident ) ) - return 1; - } - else - /* generated by us, not useful currentrly. */ - ; + if( q == ident ) { + return 1; + } + } + else if( arrayp( q ) ) + { + if( find_identifier( q, ident ) ) + return 1; + } + } +} + +array resolve_obj_defines() +{ + array res = ({}); + + foreach( need_obj_defines; string key; int|string id ) + { + if( intp( id ) ) + { + m_delete( need_obj_defines, key ); + continue; /* type in this file. Not external. */ } + } + if( sizeof( need_obj_defines ) ) + { + res += ({ "{ int i=0;\n"}); + res += ({ " ___cmod_ext_used=xalloc(sizeof(___cmod_ext_used[0]) * "+(sizeof(need_obj_defines)||1)+");\n" }); + foreach( need_obj_defines; string key; string id ) + { + int local_id = ++gid; + res += ({ + sprintf("#ifndef %s\n" + "# define %[0]s %s\n" + "{\n" + " struct program *tmp = resolve_program(" + allocate_string(sprintf("%O",id)) + ");\n" + " if( tmp ) {\n" + " ___cmod_ext_used[i].from = %d;\n" + " ___cmod_ext_used[i].to = tmp->id;\n" + " i++;\n" + " }\n" + "}\n" + "#endif\n" + ,key,sprintf("%O",sprintf("\3\0\x7f%3c", local_id)),local_id) + }); + } + res += ({ " ___cmod_ext_used[i].from = 0;\n}\n"}); + } + return res; } int main(int argc, array(string) argv) @@ -2979,7 +3034,10 @@ int main(int argc, array(string) argv) tmp->declarations += ({ "\n\n" + "#define CMOD_MAP_PROGRAM_IDS_DEFINED 1\n" + "static int ___cmod_map_program_ids(int id);\n" "#ifndef TYPEOF\n" + "static void set_program_id_to_id(void*UNUSED(id)){}\n" "/* Compat with older Pikes. */\n" "#define TYPEOF(SVAL)\t((SVAL).type)\n" "#define SUBTYPEOF(SVAL)\t((SVAL).subtype)\n" @@ -2992,15 +3050,26 @@ int main(int argc, array(string) argv) " SET_SVAL_TYPE((SVAL), (TYPE));\t\t\t\\\n" " SET_SVAL_SUBTYPE((SVAL), (SUBTYPE));\t\t\\\n" " } while(0)\n" + "#else /* */\n" + "PMOD_EXPORT void set_program_id_to_id( int (*to)(int) );\n" "#endif /* !TYPEOF */\n" "\n\n", - // FIXME: Ought to default to static in 7.9. + "#ifndef DEFAULT_CMOD_STORAGE\n" "#define CMOD_COND_USED\n" "#define DEFAULT_CMOD_STORAGE static\n" "#endif\n" }); + + tmp->addfuncs = + IFDEF("CMOD_MAP_PROGRAM_IDS_DEFINED", + ({"set_program_id_to_id( ___cmod_map_program_ids );"})) + + resolve_obj_defines() + + tmp->addfuncs + + IFDEF("CMOD_MAP_PROGRAM_IDS_DEFINED", + ({"set_program_id_to_id( 0 );"})); + if (last_str_id) { // Add code for allocation and deallocation of the strings. tmp->addfuncs = @@ -3044,22 +3113,47 @@ int main(int argc, array(string) argv) } } - x=tmp->code; + x = tmp->code; - foreach( check_used; string key; ) + x +=({ + "\n" + "#ifdef CMOD_MAP_PROGRAM_IDS_DEFINED\n" + "static int ___cmod_map_program_ids(int id)\n" + "{\n" + " int i = 0;\n" + " if( (id&0x7f000000) != 0x7f000000 ) return id;\n" + " id = id&0x00ffffff;\n" + }); + + foreach( map_types; int i; string how ) { - tmp->declarations += ({ - "#ifndef CMOD_COND_USED\n" - "# define "+key+"_used 1\n" - "#else\n" - }); - if( find_identifier( x, key ) ) - tmp->declarations +=({ "#define "+key+"_used 1\n" }); - else - tmp->declarations += ({ "#undef "+key+"_used\n" }); - tmp->declarations += ({ "#endif\n" }); + if( how[0] ) + x += ({ "#ifdef "+how[0]+"\n" }); + x += ({ "if(id=="+i+") "+how[1]+"\n" }); + if( how[0] ) + x += ({ "#endif\n" }); } + if( sizeof( need_obj_defines ) ) + { + tmp->declarations += ({ + "static struct ext_used { INT32 from;INT32 to; } *___cmod_ext_used;\n" + }); + + x += ({ + " while(___cmod_ext_used[i].from ) {\n" + " if( ___cmod_ext_used[i].from == id ) return ___cmod_ext_used[i].to;\n" + " i++;\n" + " }\n" + }); + } + x += ({ + " return 0;\n" + "}\n" + "#endif /* CMOD_MAP_PROGRAM_IDS_DEFINED */\n" + }); + + tmp->code = x; x=recursive(replace,x,PC.Token("INIT",0),tmp->addfuncs); int need_init; if ((need_init = equal(x, tmp->code))) @@ -3095,6 +3189,20 @@ int main(int argc, array(string) argv) // FIXME: This line is fishy; there is no optfuncs in ParseBlock. x=recursive(replace,x,PC.Token("OPTIMIZE",0),tmp->optfuncs); + foreach( check_used; string key; ) + { + tmp->declarations += ({ + "#ifndef CMOD_COND_USED\n" + "# define "+key+"_used 1\n" + "#else\n" + }); + if( find_identifier( x, key ) ) + tmp->declarations +=({ "#define "+key+"_used 1\n" }); + else + tmp->declarations += ({ "#undef "+key+"_used\n" }); + tmp->declarations += ({ "#endif\n" }); + } + tmp->code = x; x=recursive(replace,x,PC.Token("DECLARATIONS",0),tmp->declarations);