📄 pdoh.cpp
字号:
if( aval.IndexOfKwi("general")!=-1 ) sections |= (1<<(sGen-1)); if( aval.IndexOfKwi("use")!=-1 ) sections |= (1<<(sUse-1)); if( aval.IndexOfKwi("implement")!=-1 ) sections |= (1<<(sImpl-1)); if( aval.IndexOfKwi("library")!=-1 ) sections |= (1<<(sLib-1)); if( aval.Size() && isdigit(aval[0][0]) ) sections = atoi(aval[0]); } if( GetAValI(pc1,aval,"tofile") ){ got_word = true; file_sections = 0; if( aval.IndexOfKwi("general")!=-1 ) file_sections |= (1<<(sGen-1)); if( aval.IndexOfKwi("use")!=-1 ) file_sections |= (1<<(sUse-1)); if( aval.IndexOfKwi("implement")!=-1 ) file_sections |= (1<<(sImpl-1)); if( aval.IndexOfKwi("library")!=-1 ) file_sections |= (1<<(sLib-1)); if( aval.Size() && isdigit(aval[0][0]) ) file_sections = atoi(aval[0]); } if( GetAValIAt(pc1,aval,"library",(const char**)&pc1) ){ printf("Found library insertion point\n"); got_word = true; // Make a new library section to follow immediately here pfs = new FileSect(sLib); afs.Push(pfs); // Include library section be default sections |= 1<<(sLib-1); if( aval.IndexOfKwi("advanced")!=-1 ) adv_lib = true; // Insert library code here if( GetAValIAt(pc1,aval,"types",(const char**)&pc1) ){ StrBufKwi type; CharBuf name; Type *pt; // The value of types is an array of strings like // DerCl1(both):BaseCl1(name),... for( int ix=0; ix<aval.Size(); ix++ ){ const char *pc = aval[ix]; // This reads the derived class name if( GetAValIAtAny( pc, type, name, &pc) ){ //if( !(pt=EapFind(acl,name.Get())) ) if( !(pt=acl.Find(name.Get())) ) acl.Push( pt = new Type(name,false,true) ); if( type.IndexOfKwi("both")!=-1 ) pt->m_chk_der = ctBoth; else if( type.IndexOfKwi("either")!=-1 ) pt->m_chk_der = ctEither; else if( type.IndexOfKwi("name")!=-1 ) pt->m_chk_der = ctName; else if( type.IndexOfKwi("id")!=-1 ) pt->m_chk_der = ctId; pc = (char*)SkipSpace(pc); if( *pc==':' ){ pc++; // This reads the base class name if( GetAValIAtAny( pc, type, name, &pc) ){ if( !pt->m_bases.Size() ) pt->m_bases.Push(name); if( strcmp(pt->m_bases[0],name) ) printf( "(%d) Conflicting base class name found in library declaration: %s, %s\n", line, pt->m_bases[0].Get(), name.Get() ); if( type.IndexOfKwi("both")!=-1 ) pt->m_chk_base = ctBoth; else if( type.IndexOfKwi("either")!=-1 ) pt->m_chk_base = ctEither; else if( type.IndexOfKwi("name")!=-1 ) pt->m_chk_base = ctName; else if( type.IndexOfKwi("id")!=-1 ) pt->m_chk_base = ctId; } } } } } } if( GetAValIAt(pc1,aval,"class",(const char**)&pc1) ){ //printf( "Found class %s\n", pc1 ); got_word = true; // Class declaration to follow bool is_di = (aval.IndexOfKwi("dyni")!=-1) || (aval.IndexOfKwi("dynobj")!=-1); do_next_cl = true; acl.Push(new Type(NULL,is_di,false)); if( aval.IndexOfKwi("vobj")!=-1 ) acl.Top()->m_is_vobj = true; acl.Top()->m_user_type = (aval.IndexOfKwi("usertype")!=-1); if( GetAValI(pc1,aval,"name") && aval.Size()>0 ) acl.Top()->m_name = aval[0]; if( GetAValI(pc1,aval,"bases") ) acl.Top()->m_bases.MoveFrom(aval); if( GetAValI(pc1,aval,"version") ) acl.Top()->m_version = atoi(aval[0]); if( GetAValI(pc1,aval,"flags") && aval.Size()>0 ){ if( aval.IndexOfKwi("notypeid")!=-1 ) acl.Top()->m_skip_tid = true; //if( aval.IndexOfKwi("keepi")!=-1 ) // acl.Top()->m_keep_I = true; if( aval.IndexOfKwi("usertype")!=-1 ) acl.Top()->m_user_type = true; if( aval.IndexOfKwi("inst2reg")!=-1 ) acl.Top()->m_inst2reg = true; if( aval.IndexOfKwi("novcorr")!=-1 ) acl.Top()->m_novcorr = true; if( aval.IndexOfKwi("static")!=-1 ) acl.Top()->m_static_type = true; if( aval.IndexOfKwi("noproto")!=-1 ) acl.Top()->m_no_proto = true; if( aval.IndexOfKwi("template")!=-1 ) acl.Top()->m_is_template = true; } } if( !got_word ){ printf("Error (%d): Unknown %%DYNOBJ keyword found: %s\n",line,pc); fclose(pf); return -2; } } } else{ if( strstr(buf,"_TYPE_ID") && strstr(buf,"#define") ) type_ids.Push(buf); if( !in_auto ){ // Only keep lines when not in auto section pfs->m_sb.Push(buf); in_comment = StripComment(buf,in_comment); if( !in_comment ){ if( strstr(buf,"#endif") ) last_endif = pfs->m_sb.Top(); // Is it an ifdef line? pc = (char*)SkipSpace(buf); if( !strnicmp(pc,"#if",3) ) defines.Push(buf); else if( !strnicmp(pc,"#endif",6) ){ if( defines.Size() ) defines.Pop(); } else if( (!strnicmp(pc,"#define",7) || !strnicmp(pc,"#undef",6)) && defines.Size() ){ // See if we're just defining last #ifndef const char *pc1 = SkipSpace(SkipToSpace(pc)); static CharBuf cb; cb.Assign(pc1,SkipToSpace(pc1)-pc1); if( strstr(defines.Top(),cb) ) defines.Top() = ""; // Set to nothing } } if( !in_comment && do_next_cl && (!(is_struct=!((pc=strstr(buf,"class")))) || (pc=strstr(buf,"struct"))) ){ char *pcol = strchr(pc,':'); if( !pcol ) pcol = strchr(pc,'{'); if( pcol ){ // Find class name Type *pt = acl.Top(); pt->m_is_struct = is_struct; pt->m_defines = defines; if( !pt->m_name.Length() ) pt->m_name = GetWordRev(pcol-1); // Only read bases if not given in tag if( !pt->m_bases.Size() ){ // Find each base class - before ' or { or eol pc = pcol; if( *pcol==':' ){ // Must have : for base classes while( 1 ){ char ch, *pc1 = strchr(pc,','); if( !pc1 ) pc1 = strchr(pc,'{'); if( !pc1 ) pc1 = pc+strlen(pc); ch = *pc1; pt->m_bases.Push(GetWordRev(pc1-1)); if( ch!=',' ) break; pc = pc1+1; } } } } } } else{ // In Auto, } if( !in_comment ) do_next_cl = false; } } fclose(pf); // If no class declarations found, quit if( !acl.Size() ){ printf("No class declarations found, nothing to do, exiting.\n"); return 0; } CharBuf cb; // Caching only makes sense when writing to a file bool on_file = GetOpt(argc,argv,"-o")!=NULL; if( on_file ){ //printf( "%x %x\n", chk_sum1, chk_sum2 ); // See if checksum same as last. Then quit. CharBuf cb_cache = argv[1]; pc = (char*)strrchr(cb_cache,'/'); if( !pc ) pc = (char*)strrchr(cb_cache,'\\'); int name_pos = pc ? pc+1-cb_cache : 0; if( pc ) pc[1]=0; else cb_cache.Reset(); int nl = strlen(argv[1]+name_pos); bool is_modified = true, found_entry=false; cb_cache += ".pdoh-cache.txt"; //printf("%s\n",(const char*)cb_cache); if( cb.LoadFromFile( cb_cache ) ){ const char *pc1 = strstr(cb,argv[1]+name_pos); if( pc1 ){ // Found entry found_entry = true; int chk1, chk2; sscanf(pc1+nl+1,"%x",&chk1); sscanf(pc1+nl+1+9,"%x",&chk2); //printf( "old: %08x %08x\n", chk1, chk2 ); if( chk1==chk_sum1 && chk2==chk_sum2 ){ // Same check sum, no need to update anything //printf( "Checksum match, exiting\n" ); return 0; } // Update checksums in contents char buf[32]; sprintf( buf,"%08x", chk_sum1 ); memcpy( (char*)pc1+nl+1, buf, 8 ); sprintf( buf,"%08x", chk_sum2 ); memcpy( (char*)pc1+nl+1+9, buf, 8 ); } } if( !found_entry ) cb += cbprintf( "%s:%08x:%08x\n", argv[1]+name_pos, chk_sum1, chk_sum2 ); cb.SaveToFile( cb_cache ); printf("Found changes, updating sections - %s\n", argv[1] ); } // Make sure we have each section int n_new_sect = 0; //if( !EapFind(afs,sGen) ){ if( !afs.Find(sGen) ){ afs.Push(new FileSect(sGen)); n_new_sect++; } //if( !EapFind(afs,sUse) ){ if( !afs.Find(sUse) ){ afs.Push(new FileSect(sUse)); n_new_sect++; } //if( !EapFind(afs,sImpl) ){ if( !afs.Find(sImpl) ){ afs.Push(new FileSect(sImpl)); n_new_sect++; } //if( !EapFind(afs,sLib) ){ if( !afs.Find(sLib) ){ afs.Push(new FileSect(sLib)); n_new_sect++; } // Generate sections // Get a good random seed (2nd time) srand( (rand()<<16) + (rl_sum<<8) + *(int*)(buf+(rand()%48)) + acl.Size()*7261612 ); // For generating type IDs // We need this string in a couple of places cb = "DO_IMPLEMENT_"; cb += FileNamePart(argv[1]); ToDefineSymbol( (char*)cb.Get() ); CharBuf cb_ifdef_impl = "#ifdef "+cb; pfs = afs.Find(sGen); StrBuf &sb(pfs->m_sb); sb.Push("// %%DYNOBJ section general"); sb.Push("// This section is auto-generated and manual changes will be lost when regenerated!!"); if( is_header ){ sb.Push(cb_ifdef_impl); sb.Push(" #define DO_IMPLEMENTING // If app has not defined it already"); sb.Push("#endif"); } else // Source file sb.Push("#define DO_IMPLEMENTING // Source file, always implementing"); sb.Push("#include \"dynobj/DynObj.h\""); if( is_header && !brief ){ sb.Push("//"); sb.Push("// These are general definitions & declarations used on both the user side [main program]"); sb.Push("// and the implementor [library] side. "); } sb.Push(""); if( !brief ) sb.Push("//"); sb.Push("// --- Integer type ids for defined interfaces/classes ---"); int prev_sz = sb.Size(); // For each class, define TYPE_ID StrBuf type_id_defs; int max_id_len = 0; for( EapIter<Type*> it(acl); it(); it++ ){ if( !it()->m_name ){ // Undefined class - remove delete it(); acl.RemoveIndexUnordered(it.Index()); it--; continue; } //strcpy(buf,it()->m_name); cb = it()->m_name; for( pc=cb.Str(); *pc; pc++){ *pc=toupper(*pc); //if( *pc=='<' || *pc=='>' ) printf("Warning: Template types not supported: %s (use typedef for it)\n",buf); } UnTemplate( cb.Str(), true ); /* // Take version number from interface name? - NO GOOD if( it()->m_version==1 && isdigit(pc[-1]) ){ while( isdigit(pc[-1]) ) pc--; it()->m_version = atoi(pc); while( isdigit(pc[0]) ) pc++; } */ //strcat(buf,"_TYPE_ID"); cb += "_TYPE_ID"; type_id_defs.Push(cb); if( (int)strlen(cb)>max_id_len ) max_id_len = strlen(cb); } if( max_id_len>0 ){ for( EapIter<Type*> it(acl); it(); it++ ){ if( it()->m_skip_tid || it()->m_only_in_lib ) continue; CharBuf cb_tid = type_id_defs[it.Index()]; // Align the defines cb.cbprintf( "%s ", cb_tid.Get() ); if( max_id_len+1<cb.Length() ) cb.Str()[max_id_len+1]= 0; pc = NULL; // Look among already defined type ids for( int ix=0; ix<type_ids.Size(); ix++ ) if( pc=(char*)strstr(type_ids[ix],cb_tid) ) break; if( pc ){ // Resuse old ID pc += strlen(cb_tid); cb += GetWordFwd((char*)pc); } else{ // Generate new ID // We leave the 12 low bits clear for general purpose type information // The MSB bit (31) is set for local/app-global type ID int r = 0x80000000 | ((rand()&0x7FFFF)<<12); //int r = 0; //while( r<BASE_CUSTOM_TYPE_ID ) // r = ((rand()<<16)+rand())&0xFFFFFF00; //sprintf(buf+strlen(buf),"0x%08X", r ); cb += cbprintf("0x%08X",r); } sb.Push("#define "+cb); } } if( sb.Size()==prev_sz ) sb.Pop(); else sb.Push(""); if( is_header ){ if( !brief ) sb.Push("//"); sb.Push("// --- Forward class declarations ---"); int prev_sz = sb.Size(); for( EapIter<Type*> it(acl); it(); it++ ){ if( it()->m_no_proto ) continue; cb.cbprintf( "%s %s;", it()->m_is_struct?"struct":"class", it()->m_name.Get() ); sb.Push(cb); } if( sb.Size()==prev_sz ) sb.Pop(); else sb.Push(""); prev_sz = sb.Size(); sb.Push("// --- For each declared class, doTypeInfo template specializations ---"); if( !brief ) sb.Push("// This allows creating objects from a C++ types and in run-time casts"); for( EapIter<Type*> it(acl); it(); it++ ){ cb.cbprintf( "DO_DECL_TYPE_INFO(%s,%s);", it()->m_name.Get(), type_id_defs[it.Index()].Get() ); sb.Push(cb); } if( sb.Size()==prev_sz ) sb.Pop(); else sb.Push(""); } sb.Push("// %%DYNOBJ section end"); sb.Push(""); // Generate the use section //pfs = EapFind(afs,sUse); pfs = afs.Find(sUse); StrBuf &sb1(pfs->m_sb); sb1.Push("// %%DYNOBJ section use"); sb1.Push("// This section is auto-generated and manual changes will be lost when regenerated!!"); if( !brief ){ sb1.Push("//"); sb1.Push("// Define the symbol below from -only one place- in the project using these "); sb1.Push("// interfaces/classes [the client] (to avoid multiple definitions of functions)."); sb1.Push(""); } cb = "#ifdef DO_USE_"; cb += FileNamePart(argv[1]); ToDefineSymbol( (char*)cb.Get()+10 ); if(is_header) sb1.Push(cb); sb1.Push(""); if( !brief )sb1.Push("//"); sb1.Push("// --- DoTypeName function bodies for declared interfaces/classes ---"); // For each class, implement DoTypeName function for( EapIter<Type*> it(acl); it(); it++ ){ if( it()->m_only_in_lib ) continue; cb = "const char* DoTypeName( "; cb += it()->m_name; cb += "* p ){"; sb1.Push((const char*)cb); cb = " return \""; cb += it()->m_name; cb += "\";"; sb1.Push((const char*)cb); sb1.Push("}"); } sb1.Push(""); if( !brief ) sb1.Push("//"); sb1.Push("// --- DoTypeId function bodies for declared interfaces/classes ---"); // For each class, implement DoTypeId function for( EapIter<Type*> it(acl); it(); it++ ){ if( it()->m_only_in_lib ) continue; cb = "int DoTypeId( "; cb += it()->m_name; cb += "* p ){"; sb1.Push((const char*)cb); cb = " return "; cb += type_id_defs[it.Index()]; cb += ";"; sb1.Push((const char*)cb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -