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

📄 transform.c

📁 这是关于RFC3261实现sip的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * The parse tree transformation module for SIP. * * Copyright (c) 2006 * 	Riverbank Computing Limited <info@riverbankcomputing.co.uk> *  * This file is part of SIP. *  * This copy of SIP is licensed for use under the terms of the SIP License * Agreement.  See the file LICENSE for more details. *  * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */#include <stddef.h>#include <string.h>#include <stdlib.h>#include "sip.h"static int sameArgType(argDef *,argDef *,int);static int supportedType(classDef *,overDef *,argDef *,int);static int sameOverload(overDef *od1,overDef *od2);static int sameVirtualHandler(virtHandlerDef *vhd1,virtHandlerDef *vhd2);static int isSubClass(classDef *cc,classDef *pc);static void setAllModules(sipSpec *pt);static void ensureInput(classDef *,overDef *,argDef *);static void defaultInput(argDef *);static void defaultOutput(classDef *,overDef *,argDef *);static void assignClassNrs(sipSpec *,moduleDef *,nodeDef *);static void assignEnumNrs(sipSpec *pt);static void positionClass(classDef *);static void addNodeToParent(nodeDef *,classDef *);static void addAutoOverload(sipSpec *,classDef *,overDef *);static void ifaceFileIsUsed(sipSpec *, ifaceFileDef *, argDef *);static void ifaceFilesAreUsed(sipSpec *, ifaceFileDef *, overDef *);static void ifaceFilesAreUsedByMethod(sipSpec *, classDef *, memberDef *);static void ifaceFilesAreUsedFromOther(sipSpec *pt, signatureDef *sd);static void scopeDefaultValue(sipSpec *,classDef *,argDef *);static void setHierarchy(sipSpec *,classDef *,classDef *,classList **);static void transformCtors(sipSpec *,classDef *);static void transformCasts(sipSpec *,classDef *);static void addDefaultCopyCtor(classDef *);static void transformOverloads(sipSpec *,classDef *,overDef *);static void transformVariableList(sipSpec *);static void transformMappedTypes(sipSpec *);static void getVisibleMembers(sipSpec *,classDef *);static void getVirtuals(sipSpec *pt,classDef *cd);static void getClassVirtuals(classDef *,classDef *);static void transformTypedefs(sipSpec *pt);static void resolveMappedTypeTypes(sipSpec *,mappedTypeDef *);static void resolveCtorTypes(sipSpec *,classDef *,ctorDef *);static void resolveFuncTypes(sipSpec *,moduleDef *,classDef *,overDef *);static void resolvePySigTypes(sipSpec *,moduleDef *,classDef *,overDef *,signatureDef *,int);static void resolveVariableType(sipSpec *,varDef *);static void fatalNoDefinedType(scopedNameDef *);static void getBaseType(sipSpec *,moduleDef *,classDef *,argDef *);static void searchScope(sipSpec *,classDef *,scopedNameDef *,argDef *);static void searchMappedTypes(sipSpec *,scopedNameDef *,argDef *);static void searchTypedefs(sipSpec *,scopedNameDef *,argDef *);static void searchEnums(sipSpec *,scopedNameDef *,argDef *);static void searchClasses(sipSpec *,moduleDef *mod,scopedNameDef *,argDef *);static void appendToMRO(mroDef *,mroDef ***,classDef *);static void moveClassCasts(sipSpec *pt, classDef *cd);static void moveGlobalSlot(sipSpec *pt, memberDef *gmd);static void filterVirtualHandlers(sipSpec *pt,moduleDef *mod);static ifaceFileDef *getIfaceFile(argDef *ad);static mappedTypeDef *instantiateMappedTypeTemplate(sipSpec *pt, moduleDef *mod, mappedTypeTmplDef *mtt, argDef *type);static classDef *getProxy(sipSpec *pt, classDef *cd);/* * Transform the parse tree. */void transform(sipSpec *pt){	moduleDef *mod;	moduleListDef *mld;	classDef *cd, *rev, **tail;	classList *newl;	overDef *od;	mappedTypeDef *mtd;	virtHandlerDef *vhd;	if (pt -> module -> name == NULL)		fatal("No %%Module has been specified for the module\n");	/*	 * The class list has the main module's classes at the front and the	 * ones from the module at the most nested %Import at the end.  This	 * affects some of the following algorithms, eg. when assigning class	 * numbers.  We have to have consistency whenever a module is used.  To	 * achieve this we reverse the order of the classes.	 */	rev = NULL;	cd = pt -> classes;	while (cd != NULL)	{		classDef *next = cd -> next;		cd -> next = rev;		rev = cd;		cd = next;	}	pt -> classes = rev;	/* Build the list of all modules and number them. */	setAllModules(pt);	/* Check each class has been defined. */	for (cd = pt -> classes; cd != NULL; cd = cd -> next)		if (cd -> iff -> module == NULL)		{			fatalScopedName(classFQCName(cd));			fatal(" has not been defined\n");		}	/*	 * Set the super-class hierarchy for each class and re-order the list	 * of classes so that no class appears before a super class or an	 * enclosing scope class.	 */	newl = NULL;	for (cd = pt -> classes; cd != NULL; cd = cd -> next)		setHierarchy(pt,cd,cd,&newl);	/* Replace the old list with the new one. */	tail = &pt -> classes;	while (newl != NULL)	{		classList *cl = newl;		*tail = cl -> cd;		tail = &cl -> cd -> next;		newl = cl -> next;		free(cl);	}	*tail = NULL;	/* Transform typedefs, variables and global functions. */	transformTypedefs(pt);	transformVariableList(pt);	transformOverloads(pt,NULL,pt -> overs);	/* Transform class ctors, functions and casts. */	for (cd = pt -> classes; cd != NULL; cd = cd -> next)	{		transformCtors(pt,cd);		if (!pt -> genc)		{			transformOverloads(pt,cd,cd -> overs);			transformCasts(pt, cd);		}	}	/* Transform mapped types based on templates. */	transformMappedTypes(pt);	/* Handle default ctors now that the argument types are resolved. */ 	if (!pt -> genc)        	for (cd = pt -> classes; cd != NULL; cd = cd -> next)                	if (!isOpaque(cd))                        	addDefaultCopyCtor(cd);	/*	 * Go through each class and add it to it's defining module's tree of	 * classes.  The tree reflects the namespace hierarchy.	 */	for (cd = pt -> classes; cd != NULL; cd = cd -> next)		addNodeToParent(&cd -> iff -> module -> root,cd);	for (cd = pt -> classes; cd != NULL; cd = cd -> next)		positionClass(cd);	/* Assign module specific class numbers for all modules. */	for (mod = pt->modules; mod != NULL; mod = mod->next)		assignClassNrs(pt, mod,&mod->root);	/* Assign module specific enum numbers for all enums. */	assignEnumNrs(pt);	/* Add any automatically generated methods. */	for (cd = pt -> classes; cd != NULL; cd = cd -> next)		for (od = cd -> overs; od != NULL; od = od -> next)			if (isAutoGen(od))				addAutoOverload(pt,cd,od);	/* Allocate mapped types numbers. */	for (mtd = pt -> mappedtypes; mtd != NULL; mtd = mtd -> next)		mtd -> mappednr = mtd -> iff -> module -> nrmappedtypes++;	/*	 * Move casts and slots around to their correct classes (if in the same	 * module) or create proxies for them (if cross-module).	 */	if (!pt -> genc)	{		memberDef *md;        	for (cd = pt -> classes; cd != NULL; cd = cd -> next)			if (cd->iff->module == pt->module)				moveClassCasts(pt, cd);		for (md = pt->othfuncs; md != NULL; md = md->next)			if (md->slot != no_slot && md->module == pt->module)				moveGlobalSlot(pt, md);	}	/* Generate the different class views. */	for (cd = pt -> classes; cd != NULL; cd = cd -> next)	{		ifaceFileDef *iff = cd -> iff;		if (iff -> type == class_iface)		{			/* Get the list of visible member functions. */			getVisibleMembers(pt,cd);			/* Get the virtual members. */			if (hasShadow(cd))				getVirtuals(pt,cd);		}		else if (iff -> type == namespace_iface && iff -> module == pt -> module)		{			memberDef *md;			for (md = cd -> members; md != NULL; md = md -> next)				ifaceFilesAreUsedByMethod(pt, cd, md);		}	}        /*	 * In case there are any global functions that need external interface	 * files.	 */	for (od = pt -> overs; od != NULL; od = od -> next)		if (od->common->module == pt->module)			ifaceFilesAreUsedFromOther(pt, &od->pysig);	/*	 * Remove redundant virtual handlers.  It's important that earlier,	 * ie. those at the deepest level of %Import, are done first.	 */	for (mld = pt->allimports; mld != NULL; mld = mld->next)		filterVirtualHandlers(pt,mld -> module);	filterVirtualHandlers(pt,pt -> module);	/*	 * Make sure we have the interface files for all types from other	 * modules that are used in virtual handlers implemented in this	 * module.	 */	for (vhd = pt->module->virthandlers; vhd != NULL; vhd = vhd->next)		if (!isDuplicateVH(vhd))			ifaceFilesAreUsedFromOther(pt, vhd->sd);	/* Update proxies with some information from the real classes. */	for (cd = pt->proxies; cd != NULL; cd = cd->next)		cd->classnr = cd->real->classnr;}/* * Set the list of all modules and number them.  The list is ordered so that * a module appears before any module that imports it. */static void setAllModules(sipSpec *pt){	int nr, none;	moduleListDef **tail;	/*	 * We do multiple passes until there is a pass when nothing was done.	 */	nr = 0;	tail = &pt->allimports;	do	{		moduleDef *mod;		none = TRUE;		for (mod = pt->modules; mod != NULL; mod = mod->next)		{			moduleListDef *mld;			/* Skip the main module and anything already done. */			if (mod == pt->module || isOrdered(mod))				continue;			/* This can be done if it only has ordered imports. */			for (mld = mod->imports; mld != NULL; mld = mld->next)				if (!isOrdered(mld->module))					break;			if (mld != NULL)				continue;			/* Append this to the ordered list. */			mld = sipMalloc(sizeof (moduleListDef));			mld->module = mod;			mld->next = NULL;			*tail = mld;			tail = &mld->next;			mod->modulenr = nr++;			setIsOrdered(mod);			none = FALSE;		}	}	while (!none);}/* * Move any class casts to its correct class, or publish as a ctor extender. */static void moveClassCasts(sipSpec *pt, classDef *cd){	argList *al;	for (al = cd->casts; al != NULL; al = al->next)	{		classDef *dcd = al->arg.u.cd;		ctorDef *ct, **ctp;		argDef *ad;		/*		 * If the destination class is in a different module then use		 * a proxy.		 */		if (dcd->iff->module != pt->module)			dcd = getProxy(pt, dcd);		/* Create the new ctor. */		ct = sipMalloc(sizeof (ctorDef));		ct->ctorflags = SECT_IS_PUBLIC | CTOR_CAST;		ct->cppsig = &ct->pysig;		ct->exceptions = NULL;		ct->methodcode = NULL;		ct->prehook = NULL;		ct->posthook = NULL;		ct->next = NULL;		/* Add the source class as the only argument. */		ad = &ct->pysig.args[0];		ad->atype = class_type;		ad->name = NULL;		ad->argflags = ARG_IN | (al->arg.argflags & (ARG_IS_REF | ARG_IS_CONST));		ad->nrderefs = al->arg.nrderefs;		ad->defval = NULL;		ad->u.cd = cd;		ifaceFileIsUsed(pt, dcd->iff, ad);		ct->pysig.nrArgs = 1;		/* Append it to the list. */		for (ctp = &dcd->ctors; *ctp != NULL; ctp = &(*ctp)->next)			if (sameSignature(&(*ctp)->pysig, &ct->pysig, FALSE))			{				fatal("operator ");				fatalScopedName(classFQCName(dcd));				fatal("::");				fatalScopedName(classFQCName(dcd));				fatal("(");				fatalScopedName(classFQCName(cd));				fatal(") already defined\n");			}		*ctp = ct;	}}/* * If possible, move a global slot to its correct class. */static void moveGlobalSlot(sipSpec *pt, memberDef *gmd){	overDef **odp = &pt->overs, *od;	while ((od = *odp) != NULL)	{		int second;		argDef *arg0, *arg1;		memberDef *md, **mdhead;		overDef **odhead;		moduleDef *mod;		nameDef *nd;		if (od->common != gmd)		{			odp = &od->next;			continue;		}		/*		 * We know that the slot has the right number of arguments, but		 * the first or second one needs to be a class or enum defined		 * in the same module.  Otherwise we leave it as it is and		 * publish it as a slot extender.		 */		arg0 = &od->pysig.args[0];		arg1 = &od->pysig.args[1];		second = FALSE;		nd = NULL;		if (arg0->atype == class_type)		{			mdhead = &arg0->u.cd->members;			odhead = &arg0->u.cd->overs;			mod = arg0->u.cd->iff->module;		}		else if (arg0->atype == enum_type)		{			mdhead = &arg0->u.ed->slots;			odhead = &arg0->u.ed->overs;			mod = arg0->u.ed->module;			nd = arg0->u.ed->pyname;		}		else if (arg1->atype == class_type)		{			mdhead = &arg1->u.cd->members;			odhead = &arg1->u.cd->overs;			mod = arg1->u.cd->iff->module;			second = TRUE;		}		else if (arg1->atype == enum_type)		{			mdhead = &arg1->u.ed->slots;			odhead = &arg1->u.ed->overs;			mod = arg1->u.ed->module;			nd = arg1->u.ed->pyname;			second = TRUE;		}		else		{			fatal("One of the arguments of ");			prOverloadName(stderr, od);			fatal(" must be a class or enum\n");		}		/*		 * For rich comparisons the first argument must be a class or		 * an enum.  For cross-module slots then it may only be a		 * class.  (This latter limitation is artificial, but is		 * unlikely to be a problem in practice.)		 */		if (isRichCompareSlot(gmd))		{			if (second)			{				fatal("The first argument of ");				prOverloadName(stderr, od);				fatal(" must be a class or enum\n");			}			if (mod != gmd->module && arg0->atype == enum_type)			{				fatal("The first argument of ");				prOverloadName(stderr, od);				fatal(" must be a class\n");			}		}		if (mod != gmd->module)		{			if (isRichCompareSlot(gmd))			{				classDef *pcd = getProxy(pt, arg0->u.cd);				memberDef *pmd;				overDef *pod;				/* Create a new proxy member if needed. */				for (pmd = pcd->members; pmd != NULL; pmd = pmd->next)					if (pmd->slot == gmd->slot)						break;				if (pmd == NULL)				{					pmd = sipMalloc(sizeof (memberDef));					pmd->pyname = gmd->pyname;					pmd->memberflags = 0;					pmd->slot = gmd->slot;					pmd->module = mod;					pmd->next = pcd->members;					pcd->members = pmd;				}				/* Add the proxy overload. */				pod = sipMalloc(sizeof (overDef));				*pod = *od;				pod->common = pmd;				pod->next = pcd->overs;				pcd->overs = pod;				/* Remove the first argument. */				pod->pysig.args[0] = pod->pysig.args[1];				pod->pysig.nrArgs = 1;				/* Remove from the list. */				*odp = od->next;			}			else				odp = &od->next;			continue;		}		/* Remove from the list. */		*odp = od->next;		/*		 * The only time we need the name of an enum is when it has		 * slots.		 */		if (nd != NULL)			setIsUsedName(nd);		/* See if there is already a member or create a new one. */		for (md = *mdhead; md != NULL; md = md->next)			if (md->slot == gmd->slot)				break;		if (md == NULL)		{			md = sipMalloc(sizeof (memberDef));			*md = *gmd;			md->module = mod;			md->next = *mdhead;			*mdhead = md;		}		/* Move the overload. */		setIsPublic(od);		od->common = md;		od->next = *odhead;		*odhead = od;		/* Remove the first argument of comparison operators. */		if (isRichCompareSlot(md))		{			*arg0 = *arg1;			od->pysig.nrArgs = 1;		}	}}/* * Create a proxy for a class if it doesn't already exist.  Proxies are used as * containers for cross-module extenders. */static classDef *getProxy(sipSpec *pt, classDef *cd){	classDef *pcd;	for (pcd = pt->proxies; pcd != NULL; pcd = pcd->next)		if (pcd->iff == cd->iff)			return pcd;	pcd = sipMalloc(sizeof (classDef));	pcd->classflags = 0;	pcd->classnr = -1;	pcd->pyname = cd->pyname;	pcd->iff = cd->iff;	pcd->ecd = cd->ecd;	pcd->real = cd;	pcd->node = NULL;	pcd->supers = cd->supers;	pcd->mro = cd->supers;	pcd->td = NULL;	pcd->ctors = NULL;	pcd->defctor = NULL;	pcd->dealloccode = NULL;	pcd->dtorcode = NULL;	pcd->dtorexceptions = NULL;	pcd->members = NULL;	pcd->overs = NULL;	pcd->casts = NULL;	pcd->vmembers = NULL;	pcd->visible = NULL;	pcd->cppcode = NULL;	pcd->hdrcode = NULL;	pcd->convtosubcode = NULL;	pcd->subbase = NULL;	pcd->convtocode = NULL;	pcd->travcode = NULL;	pcd->clearcode = NULL;	pcd->readbufcode = NULL;	pcd->writebufcode = NULL;	pcd->segcountcode = NULL;	pcd->charbufcode = NULL;	pcd->next = pt->proxies;	pt->proxies = pcd;	return pcd;}/* * Go through the virtual handlers filtering those that can duplicate earlier * ones.  Make sure each virtual is numbered within its module, and according * to their position in the list (ignoring duplicates). */static void filterVirtualHandlers(sipSpec *pt,moduleDef *mod){	virtHandlerDef *vhd;	for (vhd = mod -> virthandlers; vhd != NULL; vhd = vhd -> next)	{		virtHandlerDef *best, *best_thismod, *hd;		best = best_thismod = NULL;		/*		 * If this has handwritten code then we will want to use it.		 * Otherwise, look for a handler in earlier modules.		 */		if (vhd -> virtcode == NULL)		{			moduleListDef *mld;			for (mld = pt->allimports; mld != NULL && mld->module != mod; mld = mld->next)			{				for (hd = mld -> module -> virthandlers; hd != NULL; hd = hd -> next)					if (sameVirtualHandler(vhd,hd))					{						best = hd;						break;					}				/*				 * No need to check later modules as this will				 * either be the right one, or a duplicate of				 * the right one.				 */				if (best != NULL)					break;			}		}		/*		 * Find the best candidate in this module in case we want to		 * give it our handwritten code.		 */		for (hd = mod -> virthandlers; hd != vhd; hd = hd -> next)			if (sameVirtualHandler(vhd,hd))

⌨️ 快捷键说明

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