⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdoh.cpp

📁 The library provides supports for run-time loaded plugin classes in C++
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Copyright (c) 2007, Arne Steinarson// Licensing for DynObj project - see DynObj-license.txt in parent folder/*	This is a utility to parse through DynObj header files and generate type 	related declarations, definitions and functions.		It triggers on the keyword %%DYNOBJ in comments:	      %%DYNOBJ class(dyni) bases(MainBase,SideBase1,...,SideBaseN)         which informs it that an exported class, derived from DynI, comes below.   The bases part can be omitted and then it parses the declaration of the    class to retrieve those (taking all bases).       The "bases" attribute allows for filtering what types one makes visible.   Sometimes the direct base class should not be visible, but rather one    of its ancestors.      For types not derived from DynI (we call them VObj), the declaration is:         %%DYNOBJ VObj bases(MainBase,SideBase1,...,SideBaseN)   Three sections in the header file are generated:           %%DYNOBJ section general      %%DYNOBJ section use      %%DYNOBJ section implement      which each end with:         %%DYNOBJ section end   	When the file has been generated once, you can move the auto generated 	sections around, and they will stay there, when redone. 	The general section defines the integer type IDs. If a file is remade, they 	will stay the same. It also adds prototypes for type -> name and type -> id	functions.		The use section is included from the main program that uses the library.		The implement section is should be included from the library, it provides	type declarations and default bodies for doGetType functions.*//*#include "malloc.h"#include "utils/sqmem.h"void * operator new (size_t size){	void *pv = sq_vm_malloc( size );	return pv;}void * operator new[] (size_t size){	return operator new(size);}void operator delete (void * pv){	sq_vm_free( pv );}void operator delete[] (void *pv){	operator delete(pv);}*/#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <time.h>#define EXPARRP_IN_EXPARR#include "utils/ExpArr.hpp"//#include "utils/utf8String.h"#include "utils/StringBuffer.h"#include "utils/utils.h"#include "utils/StrUtils.h"#include "utils/FileSections.h"#include "../DynObj.h"//#define StrBuf StringBuffer void PDOH_BP_Dummy(){	puts("BPDummy\n");}// Only looks at the beginning for namebool GetAValIAt( const char *pc, StrBuf &sb, const char *name, const char** pc_next=NULL, bool name_found=false) {	sb.Empty();	if( !pc || !name ) return false;	if( !name_found ){		pc = SkipSpace(pc);		if( !keywordieq(pc,name) ) return false;		pc = SkipSpace(pc+strlen(name));	}	if( *pc!='(' ){		// When not find (...) treat as an empty array		if( pc_next ) *pc_next=pc;		return true;	}	pc = SkipSpace(pc+1);		// Loop through until we find ')'	const char *pc1;	char ch;	int br_cnt;	while( 1 ){		// For recursive behaviour, count '(' and consume ')'		br_cnt = 0;		for( pc1=pc; ch=*pc1; pc1++ ){			if( !ch ) break;			if( !br_cnt && (isspace(ch) || ch==',' || ch==')') )				break;			if( ch=='(' ) br_cnt++;			else if( ch==')' ) br_cnt--;		}		sb.Push(pc,pc1-pc);		pc = SkipSpace(pc1);		if( !*pc ) return false;		if( *pc==')' ){			if(pc_next) *pc_next = pc+1;			return true;		}		pc = SkipSpace(pc+1);	}		// Never come here	return false;}// Searches the full line for namebool GetAValI( const char *pc, StrBuf &sb, const char *name) {	pc = keywordifind(pc,name);	if( !pc ) return false;	return GetAValIAt(pc,sb,name,NULL,true);	//return GetAValIAt(pc+strlen(name),sb,name,NULL,true);}// Read the first word as an AValbool GetAValIAtAny( const char *pc, StrBuf &sb, CharBuf &name, const char** pc_next=NULL) {	if( !pc ) return false;	pc = SkipSpace(pc);	const char *pe = pc;	while( isalnum(*pe) ) pe++;	name.Assign(pc,pe-pc);	return GetAValIAt(pe,sb,name,pc_next,true);}void ToDefineSymbol( char *pc ){	for( ; *pc; pc++ ){		*pc = toupper(*pc);		if( *pc=='/' || *pc=='\\' || *pc=='-' ) *pc='_';		if( *pc=='.' ){ *pc=0; break; }	}}void RemoveSlashDots( char *pc ){	for( ; *pc; pc++ ){		if( *pc=='/' || *pc=='\\' || *pc=='-' ) *pc='_';		if( *pc=='.' ){ *pc=0; break; }	}}void UnTemplate( char *pc, bool is_define ){	for( ; *pc; pc++ ){		if( *pc=='<' || *pc=='>' ) *pc=is_define?'t':'T';		if( *pc=='*' ) *pc='p';	}}const char *FileNamePart( const char *path ){	const char *pc = strrchr(path,'/');	if( !pc ) pc=strrchr(path,'\\');	return pc ? pc+1 : path;}// Will remove comments from buffer and return true if we're still // in a commented linebool StripComment( char *buf, bool in_comment ){	char *pc;	if( in_comment ){		// Look for end of block comment		if( pc=strstr(buf,"*/") ){			memmove(buf,pc+2,strlen(pc+1));			return StripComment(buf,false);		}		else return true;	}	else{		// Look for start of block comment		if( pc=strstr(buf,"/*") )			return StripComment(pc,true);		else if( pc=strstr(buf,"//") )			*pc = 0;		return false;	}}class StrBufKwi : public StringBuffer {public:	// Look for string, case insensitive	int IndexOfI( const char *kw ){		for( int ix=0; ix<Size(); ix++ ){			if( !Elem(ix) ){				if( !kw ) return ix;			}			else if(kw && !stricmp(Elem(ix).Get(),kw))				return ix;		}		return -1;	}	// Look for keyword 	int IndexOfKwi( const char *kw ){		int kwl = kw ? strlen(kw) : 0;		for( int ix=0; ix<Size(); ix++ ){			if( !Elem(ix) ){				if( !kw ) return ix;			}			else if(kw && keywordieq(Elem(ix).Get(),kw,kwl))				return ix;		}		return -1;	}};enum SectType {	sNone=0,	sGen,	sUse,	sImpl,	sLib};class FileSect {public:	FileSect(SectType sect) : m_sect(sect) { }	StrBuf m_sb;	SectType m_sect;	bool operator == (SectType sect){ return m_sect==sect; } };// This is for checking type and/or id on creation (when generating library code)enum CheckType {	ctName = 1,	ctId = 2,	ctEither = 3,	ctBoth = 4};class Type {public:	Type(const char* name, bool is_di, bool only_in_lib) : m_name(name), 		m_is_di(is_di), m_is_vobj(is_di), m_skip_tid(false), /*m_keep_I(false),*/ 		m_user_type(false), m_inst2reg(false), m_novcorr(false), m_static_type(false), 		m_only_in_lib(only_in_lib), m_is_struct(false), m_no_proto(false),         m_is_template(false), m_version(1) { 			m_chk_der=ctEither; m_chk_base=ctBoth; 		}	CharBuf m_name;	StrBuf  m_bases;	StrBuf  m_defines;	// All the defines this one is inside	bool m_is_struct;	bool m_is_di;	bool m_is_vobj;	bool m_skip_tid;	//bool m_keep_I;	bool m_user_type;	bool m_inst2reg;	// Instantiate to register    bool m_novcorr;     // Skip VTable correction for this type    bool m_static_type; // All instances are static	bool m_only_in_lib;	bool m_no_proto;    bool m_is_template;	CheckType m_chk_der;	CheckType m_chk_base;	int  m_version;	bool operator == (const char *name){ return m_name==name; }};const char *GetOpt(int argc, const char **argv, const char *opt ){	if( !opt ) return NULL;	int ol = strlen(opt);	for( int i=0; i<argc; i++ ){		if( argv[i] && !strncmp(argv[i],opt,ol) )			return argv[i]+ol;	}	return NULL;}// Update checksums void CalcCheckSum( const char *pc, int& chk_sum1, int& chk_sum2 ){    int l = strlen(pc);    while( l>=4 ){        chk_sum1 >>= 1;        chk_sum1 += *(int*)pc;        pc += 4;        if( (l-=4)<4 ) break;        chk_sum2 *= 371;        chk_sum2 += *(int*)pc;        pc += 4;        l -= 4;    }    // Trailing bytes    while( *pc )        chk_sum1 = chk_sum1*3 + *pc++;}int main( int argc, const char **argv ){	void *pv = malloc(1);	free(pv);		if( argc<=1 || !strncmp(argv[1],"-?",2) || strstr(argv[1],"-help") ){		printf( "pdoh file.h [options] \n" );		printf( "  Option -o  overwrites input file.\n");		printf( "  Option -oFileName.h Writes output to Filename.h.\n");		printf( "  Option -sN selects sections to generate (N=1..15: 1-gen, 2-use, 4-implement, 8-library).\n");		printf( "  Option -fN section to separate file (N=1..15: 1-gen, 2-use, 4-implement, 8-library).\n");		printf( "  Option -b  brief output (minimize comments).\n");		printf( "  Option -c  treat as source file.\n");		printf( "  Option -h  treat as header file.\n");		printf( "  Option -p  Path where to find c++ template (sect-lib.fs.cpp) files. Use -p../ for parent directory..\n");		return -1;	}		int tm = (int)time(NULL); 	srand( (tm<<16) + tm + (argc*1000) + (int)argv[0] );	// For generating type IDs		FILE *pf = fopen(argv[1],"rt");	if(!pf){		printf("failed open file \'%s\' for reading\n", argv[1] );		return -1;	}	ExpArrP<FileSect*> afs;	ExpArrP<Type*> acl;	StrBuf type_ids;	bool is_header = true;	if( strstr(argv[1],".cc") || strstr(argv[1],".cpp") || strstr(argv[1],".cxx") || strstr(argv[1],".c++") )		is_header = false;	if( GetOpt(argc,argv,"-c") )		is_header = false;	if( GetOpt(argc,argv,"-h") )		is_header = true;		char *pc;	FileSect *pfs = new FileSect(sNone);	afs.Push(pfs);	bool brief = GetOpt(argc,argv,"-b") ? true : false;	bool in_auto = false;	bool do_next_cl = false;	bool in_comment = false;	bool is_struct = false;	//bool do_keep_I = false;	bool vtab_corr = false;    bool adv_lib = false;   // Generate library with placement new	int  sections = is_header ? 5 : 5;	// Output sections, general and implement for both	int  file_sections = 0;	int skip_if_space = 0;	int rl, rl_sum=0;	StrBuf defines;	const char *last_endif = NULL;	// To really put it at the end of the file (header guard)	int line = 0;    	//char buf[512];	CharBuf cb_in;	char *buf;	int cb_len = cb_in.Length();	    int chk_sum1=0, chk_sum2=0;   // Checksums to detect if we can skip file update safely		while( (rl=ReadLine(pf,cb_in,cb_len))>=0 ) {		buf = cb_in.Str();		line++;		pc = buf;		rl_sum += rl;		if( skip_if_space>0 ){			// When generating sections, we insert space after, 			// this allows for not growing that			while( *pc && isspace(*pc) ) pc++;			if( !*pc ){				skip_if_space--;				continue;			}		}		// Find tag		pc = strstr(buf,"%%");         //printf( "Found tag %s\n", buf );		if( pc ){            // If inside a comment, skip            if( in_comment && (!strstr(buf,"*/") || strstr(buf,"*/")>pc) )                pc = NULL;            else{                pc = (char*)SkipSpace(pc+2);                if( !strnicmp(pc,"DYNOBJ",6) ) pc+=6;                else pc=NULL;            }		}		if( pc ){            CalcCheckSum( pc, chk_sum1, chk_sum2 );			char *pc1 = (char*)SkipSpace(pc);			if( keywordieq(pc1,"section") ){				// Starting or ending a section, do not keep this line				pc = pc1+7;				in_auto = true;				SectType ns = (SectType)-1;				if( strstr(pc,"implement") ) ns = sImpl;				else if( strstr(pc,"use") ) ns = sUse;				else if( strstr(pc,"general") ) ns = sGen;				else if( strstr(pc,"library") ) ns = sLib;				else if( strstr(pc,"end") ){					ns = sNone;					in_auto = false; 					skip_if_space = 1;				}				if( ns==-1 ){					printf("Error (%d): Unknown %%DYNOBJ section found: %s\n",line,pc);					fclose(pf);					return -2;				}				if( pfs->m_sect!=ns ){					pfs = new FileSect(ns);					afs.Push(pfs);				}			}			else{ 				// This does not jump a section, so we add the line				StrBufKwi aval;				pfs->m_sb.Push(buf);				do_next_cl = false;				bool got_word = false;				// Global file options?				if( GetAValIAt(pc1,aval,"options") ){					got_word = true;					//if( aval.IndexOfKwi("keepi")!=-1 )					//	do_keep_I = true;					if( aval.IndexOfKwi("vtabcorr")!=-1 )						vtab_corr = true;					if( aval.IndexOfKwi("brief")!=-1 )						brief = true;				}				if( GetAValI(pc1,aval,"generate") ){					got_word = true;					sections = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -