You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
13737 lines
322 KiB
13737 lines
322 KiB
/*
|
|
* The code generator module for SIP.
|
|
*
|
|
* Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
|
|
*
|
|
* 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.
|
|
*
|
|
* This copy of SIP may also used under the terms of the GNU General Public
|
|
* License v2 or v3 as published by the Free Software Foundation which can be
|
|
* found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
|
|
*
|
|
* SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#include "sip.h"
|
|
|
|
|
|
/* Return the base (ie. C/C++) name of a super-type or meta-type. */
|
|
#define smtypeName(sm) (strrchr((sm)->name->text, '.') + 1)
|
|
|
|
/* Return TRUE if a wrapped variable can be set. */
|
|
#define canSetVariable(vd) ((vd)->type.nrderefs != 0 || !isConstArg(&(vd)->type))
|
|
|
|
|
|
/* Control what generateCalledArgs() actually generates. */
|
|
typedef enum {
|
|
Declaration,
|
|
Definition
|
|
} funcArgType;
|
|
|
|
|
|
/* An entry in the sorted array of methods. */
|
|
typedef struct {
|
|
memberDef *md; /* The method. */
|
|
} sortedMethTab;
|
|
|
|
|
|
static int currentLineNr; /* Current output line number. */
|
|
static const char *currentFileName; /* Current output file name. */
|
|
static int previousLineNr; /* Previous output line number. */
|
|
static const char *previousFileName; /* Previous output file name. */
|
|
static int exceptions; /* Set if exceptions are enabled. */
|
|
static int tracing; /* Set if tracing is enabled. */
|
|
static int generating_c; /* Set if generating C. */
|
|
static int release_gil; /* Set if always releasing the GIL. */
|
|
static const char *prcode_last = NULL; /* The last prcode format string. */
|
|
static int prcode_xml = FALSE; /* Set if prcode is XML aware. */
|
|
static int docstrings; /* Set if generating docstrings. */
|
|
|
|
|
|
static void generateDocumentation(sipSpec *pt, const char *docFile);
|
|
static void generateBuildFile(sipSpec *pt, const char *buildFile,
|
|
const char *srcSuffix, const char *consModule);
|
|
static void generateBuildFileSources(sipSpec *pt, moduleDef *mod,
|
|
const char *srcSuffix, FILE *fp);
|
|
static void generateInternalAPIHeader(sipSpec *pt, moduleDef *mod,
|
|
const char *codeDir, stringList *xsl);
|
|
static void generateCpp(sipSpec *pt, moduleDef *mod, const char *codeDir,
|
|
const char *srcSuffix, int parts, stringList *xsl);
|
|
static void generateCompositeCpp(sipSpec *pt, const char *codeDir);
|
|
static void generateConsolidatedCpp(sipSpec *pt, const char *codeDir,
|
|
const char *srcSuffix);
|
|
static void generateComponentCpp(sipSpec *pt, const char *codeDir,
|
|
const char *consModule);
|
|
static void generateSipImport(moduleDef *mod, FILE *fp);
|
|
static void generateSipImportVariables(FILE *fp);
|
|
static void generateModInitStart(moduleDef *mod, int gen_c, FILE *fp);
|
|
static void generateModDefinition(moduleDef *mod, const char *methods,
|
|
FILE *fp);
|
|
static void generateIfaceCpp(sipSpec *, ifaceFileDef *, const char *,
|
|
const char *, FILE *);
|
|
static void generateMappedTypeCpp(mappedTypeDef *mtd, sipSpec *pt, FILE *fp);
|
|
static void generateImportedMappedTypeAPI(mappedTypeDef *mtd, sipSpec *pt,
|
|
moduleDef *mod, FILE *fp);
|
|
static void generateMappedTypeAPI(sipSpec *pt, mappedTypeDef *mtd, FILE *fp);
|
|
static void generateClassCpp(classDef *cd, sipSpec *pt, FILE *fp);
|
|
static void generateImportedClassAPI(classDef *cd, sipSpec *pt, moduleDef *mod,
|
|
FILE *fp);
|
|
static void generateClassAPI(classDef *cd, sipSpec *pt, FILE *fp);
|
|
static void generateClassFunctions(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static void generateShadowCode(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static void generateFunction(sipSpec *, memberDef *, overDef *, classDef *,
|
|
classDef *, moduleDef *, FILE *);
|
|
static void generateFunctionBody(overDef *, classDef *, mappedTypeDef *,
|
|
classDef *, int deref, moduleDef *, FILE *);
|
|
static void generateTypeDefinition(sipSpec *pt, classDef *cd, FILE *fp);
|
|
static void generateTypeInit(classDef *, moduleDef *, FILE *);
|
|
static void generateCppCodeBlock(codeBlock *, FILE *);
|
|
static void generateUsedIncludes(ifaceFileList *iffl, FILE *fp);
|
|
static void generateModuleAPI(sipSpec *pt, moduleDef *mod, FILE *fp);
|
|
static void generateImportedModuleAPI(sipSpec *pt, moduleDef *mod,
|
|
moduleDef *immod, FILE *fp);
|
|
static void generateShadowClassDeclaration(sipSpec *, classDef *, FILE *);
|
|
static int hasConvertToCode(argDef *ad);
|
|
static void deleteOuts(signatureDef *sd, FILE *fp);
|
|
static void deleteTemps(signatureDef *sd, FILE *fp);
|
|
static void gc_ellipsis(signatureDef *sd, FILE *fp);
|
|
static void generateCallArgs(signatureDef *, signatureDef *, FILE *);
|
|
static void generateCalledArgs(ifaceFileDef *, signatureDef *, funcArgType,
|
|
int, FILE *);
|
|
static void generateVariable(ifaceFileDef *, argDef *, int, FILE *);
|
|
static void generateNamedValueType(ifaceFileDef *, argDef *, char *, FILE *);
|
|
static void generateBaseType(ifaceFileDef *, argDef *, int, FILE *);
|
|
static void generateNamedBaseType(ifaceFileDef *, argDef *, char *, int,
|
|
FILE *);
|
|
static void generateTupleBuilder(signatureDef *, FILE *);
|
|
static void generateEmitters(classDef *cd, FILE *fp);
|
|
static void generateEmitter(classDef *, visibleList *, FILE *);
|
|
static void generateVirtualHandler(virtHandlerDef *vhd, FILE *fp);
|
|
static void generateVirtHandlerErrorReturn(argDef *res, const char *indent,
|
|
FILE *fp);
|
|
static void generateVirtualCatcher(moduleDef *mod, classDef *cd, int virtNr,
|
|
virtOverDef *vod, FILE *fp);
|
|
static void generateVirtHandlerCall(moduleDef *mod, classDef *cd,
|
|
virtOverDef *vod, argDef *res, const char *indent, FILE *fp);
|
|
static void generateUnambiguousClass(classDef *cd, classDef *scope, FILE *fp);
|
|
static void generateProtectedEnums(sipSpec *, classDef *, FILE *);
|
|
static void generateProtectedDeclarations(classDef *, FILE *);
|
|
static void generateProtectedDefinitions(classDef *, FILE *);
|
|
static void generateProtectedCallArgs(signatureDef *sd, FILE *fp);
|
|
static void generateConstructorCall(classDef *, ctorDef *, int, int,
|
|
moduleDef *, FILE *);
|
|
static void generateHandleResult(overDef *, int, int, char *, FILE *);
|
|
static void generateOrdinaryFunction(sipSpec *pt, moduleDef *mod,
|
|
classDef *c_scope, mappedTypeDef *mt_scope, memberDef *md, FILE *fp);
|
|
static void generateSimpleFunctionCall(fcallDef *, FILE *);
|
|
static void generateFunctionCall(classDef *c_scope, mappedTypeDef *mt_scope,
|
|
ifaceFileDef *o_scope, overDef *od, int deref, moduleDef *mod,
|
|
FILE *fp);
|
|
static void generateCppFunctionCall(ifaceFileDef *scope,
|
|
ifaceFileDef *o_scope, overDef *od, FILE *fp);
|
|
static void generateSlotArg(signatureDef *sd, int argnr, FILE *fp);
|
|
static void generateComparisonSlotCall(ifaceFileDef *scope, overDef *od,
|
|
const char *op, const char *cop, int deref, FILE *fp);
|
|
static void generateBinarySlotCall(ifaceFileDef *scope, overDef *od,
|
|
const char *op, int deref, FILE *fp);
|
|
static void generateNumberSlotCall(overDef *od, char *op, FILE *fp);
|
|
static void generateVariableGetter(ifaceFileDef *, varDef *, FILE *);
|
|
static void generateVariableSetter(ifaceFileDef *, varDef *, FILE *);
|
|
static int generateObjToCppConversion(argDef *, FILE *);
|
|
static void generateVarMember(varDef *vd, FILE *fp);
|
|
static int generateVoidPointers(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static int generateChars(sipSpec *pt, moduleDef *mod, classDef *cd, FILE *fp);
|
|
static int generateStrings(sipSpec *pt, moduleDef *mod, classDef *cd, FILE *fp);
|
|
static sortedMethTab *createFunctionTable(memberDef *, int *);
|
|
static sortedMethTab *createMethodTable(classDef *, int *);
|
|
static int generateMappedTypeMethodTable(sipSpec *pt, mappedTypeDef *mtd,
|
|
FILE *fp);
|
|
static int generateClassMethodTable(sipSpec *pt, classDef *cd, FILE *fp);
|
|
static void prMethodTable(sipSpec *pt, sortedMethTab *mtable, int nr,
|
|
ifaceFileDef *iff, overDef *overs, FILE *fp);
|
|
static void generateEnumMacros(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
mappedTypeDef *mtd, FILE *fp);
|
|
static int generateEnumMemberTable(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
mappedTypeDef *mtd, FILE *fp);
|
|
static int generateInts(sipSpec *pt, moduleDef *mod, classDef *cd, FILE *fp);
|
|
static int generateLongs(sipSpec *pt, moduleDef *mod, classDef *cd, FILE *fp);
|
|
static int generateUnsignedLongs(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static int generateLongLongs(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static int generateUnsignedLongLongs(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static int generateVariableType(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
argType atype, const char *eng, const char *s1, const char *s2,
|
|
FILE *fp);
|
|
static int generateDoubles(sipSpec *pt, moduleDef *mod, classDef *cd, FILE *fp);
|
|
static int generateClasses(sipSpec *pt, moduleDef *mod, classDef *cd, FILE *fp);
|
|
static void generateTypesInline(sipSpec *pt, moduleDef *mod, FILE *fp);
|
|
static void generateAccessFunctions(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
FILE *fp);
|
|
static void generateConvertToDefinitions(mappedTypeDef *, classDef *, FILE *);
|
|
static void generateEncodedType(moduleDef *mod, classDef *cd, int last,
|
|
FILE *fp);
|
|
static int generateArgParser(signatureDef *sd, classDef *c_scope,
|
|
mappedTypeDef *mt_scope, ctorDef *ct, overDef *od, int secCall,
|
|
FILE *fp);
|
|
static void generateTry(throwArgs *, FILE *);
|
|
static void generateCatch(throwArgs *ta, signatureDef *sd, moduleDef *mod,
|
|
FILE *fp);
|
|
static void generateCatchBlock(exceptionDef *xd, signatureDef *sd, FILE *fp);
|
|
static void generateThrowSpecifier(throwArgs *, FILE *);
|
|
static void generateSlot(moduleDef *mod, classDef *cd, enumDef *ed,
|
|
memberDef *md, FILE *fp);
|
|
static void generateCastZero(argDef *ad, FILE *fp);
|
|
static void generateCallDefaultCtor(ctorDef *ct, FILE *fp);
|
|
static int countVirtuals(classDef *);
|
|
static int skipOverload(overDef *, memberDef *, classDef *, classDef *, int);
|
|
static int compareMethTab(const void *, const void *);
|
|
static int compareEnumMembers(const void *, const void *);
|
|
static char *getSubFormatChar(char, argDef *);
|
|
static char *createIfaceFileName(const char *, ifaceFileDef *, const char *);
|
|
static FILE *createCompilationUnit(moduleDef *mod, const char *fname,
|
|
const char *description);
|
|
static FILE *createFile(moduleDef *mod, const char *fname,
|
|
const char *description);
|
|
static void closeFile(FILE *);
|
|
static void prScopedName(FILE *fp, scopedNameDef *snd, char *sep);
|
|
static void prTypeName(FILE *fp, argDef *ad);
|
|
static void prScopedClassName(FILE *fp, ifaceFileDef *scope, classDef *cd);
|
|
static int isZeroArgSlot(memberDef *md);
|
|
static int isMultiArgSlot(memberDef *md);
|
|
static int isIntArgSlot(memberDef *md);
|
|
static int isInplaceNumberSlot(memberDef *md);
|
|
static int isInplaceSequenceSlot(memberDef *md);
|
|
static int needErrorFlag(codeBlock *cb);
|
|
static int needOldErrorFlag(codeBlock *cb);
|
|
static int needNewInstance(argDef *ad);
|
|
static int needDealloc(classDef *cd);
|
|
static const char *getBuildResultFormat(argDef *ad);
|
|
static const char *getParseResultFormat(argDef *ad, int res_isref, int xfervh);
|
|
static void generateParseResultExtraArgs(argDef *ad, int argnr, FILE *fp);
|
|
static char *makePartName(const char *codeDir, const char *mname, int part,
|
|
const char *srcSuffix);
|
|
static void fakeProtectedArgs(signatureDef *sd);
|
|
static void normaliseArgs(signatureDef *);
|
|
static void restoreArgs(signatureDef *);
|
|
static const char *slotName(slotType st);
|
|
static void ints_intro(classDef *cd, FILE *fp);
|
|
static const char *argName(const char *name, codeBlock *cb);
|
|
static int usedInCode(codeBlock *code, const char *str);
|
|
static void generateDefaultValue(argDef *ad, int argnr, FILE *fp);
|
|
static void generateClassFromVoid(classDef *cd, const char *cname,
|
|
const char *vname, FILE *fp);
|
|
static void generateMappedTypeFromVoid(mappedTypeDef *mtd, const char *cname,
|
|
const char *vname, FILE *fp);
|
|
static int generateSubClassConvertors(sipSpec *pt, moduleDef *mod, FILE *fp);
|
|
static void generateNameCache(sipSpec *pt, FILE *fp);
|
|
static const char *resultOwner(overDef *od);
|
|
static void prCachedName(FILE *fp, nameDef *nd, const char *prefix);
|
|
static void generateSignalTableEntry(sipSpec *pt, classDef *cd, overDef *sig,
|
|
memberDef *md, int membernr, FILE *fp);
|
|
static void generateTypesTable(sipSpec *pt, moduleDef *mod, FILE *fp);
|
|
static int py2OnlySlot(slotType st);
|
|
static int py2_5LaterSlot(slotType st);
|
|
static int keepPyReference(argDef *ad);
|
|
static int isDuplicateProtected(classDef *cd, overDef *target);
|
|
static char getEncoding(argType atype);
|
|
static void generateTypeDefName(ifaceFileDef *iff, FILE *fp);
|
|
static void generateTypeDefLink(sipSpec *pt, ifaceFileDef *iff, FILE *fp);
|
|
static int overloadHasDocstring(sipSpec *pt, overDef *od, memberDef *md);
|
|
static int hasDocstring(sipSpec *pt, overDef *od, memberDef *md,
|
|
ifaceFileDef *scope);
|
|
static void generateDocstring(sipSpec *pt, overDef *overs, memberDef *md,
|
|
const char *scope_name, classDef *scope_scope, FILE *fp);
|
|
static int overloadHasClassDocstring(sipSpec *pt, ctorDef *ct);
|
|
static int hasClassDocstring(sipSpec *pt, classDef *cd);
|
|
static void generateClassDocstring(sipSpec *pt, classDef *cd, FILE *fp);
|
|
static int isDefaultAPI(sipSpec *pt, apiVersionRangeDef *avd);
|
|
static void generateExplicitDocstring(codeBlock *docstring, FILE *fp);
|
|
static int copyConstRefArg(argDef *ad);
|
|
|
|
|
|
/*
|
|
* Generate the code from a specification.
|
|
*/
|
|
void generateCode(sipSpec *pt, char *codeDir, char *buildfile, char *docFile,
|
|
const char *srcSuffix, int except, int trace, int releaseGIL,
|
|
int parts, stringList *xsl, const char *consModule, int docs)
|
|
{
|
|
exceptions = except;
|
|
tracing = trace;
|
|
release_gil = releaseGIL;
|
|
generating_c = pt->genc;
|
|
docstrings = docs;
|
|
|
|
if (srcSuffix == NULL)
|
|
srcSuffix = (generating_c ? ".c" : ".cpp");
|
|
|
|
/* Generate the documentation. */
|
|
if (docFile != NULL)
|
|
generateDocumentation(pt,docFile);
|
|
|
|
/* Generate the code. */
|
|
if (codeDir != NULL)
|
|
{
|
|
if (isComposite(pt->module))
|
|
generateCompositeCpp(pt, codeDir);
|
|
else if (isConsolidated(pt->module))
|
|
{
|
|
moduleDef *mod;
|
|
|
|
for (mod = pt->modules; mod != NULL; mod = mod->next)
|
|
if (mod->container == pt->module)
|
|
generateCpp(pt, mod, codeDir, srcSuffix, parts, xsl);
|
|
|
|
generateConsolidatedCpp(pt, codeDir, srcSuffix);
|
|
}
|
|
else if (consModule != NULL)
|
|
generateComponentCpp(pt, codeDir, consModule);
|
|
else
|
|
generateCpp(pt, pt->module, codeDir, srcSuffix, parts, xsl);
|
|
}
|
|
|
|
/* Generate the build file. */
|
|
if (buildfile != NULL)
|
|
generateBuildFile(pt, buildfile, srcSuffix, consModule);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the documentation.
|
|
*/
|
|
static void generateDocumentation(sipSpec *pt, const char *docFile)
|
|
{
|
|
FILE *fp;
|
|
codeBlock *cb;
|
|
|
|
fp = createFile(pt->module, docFile, NULL);
|
|
|
|
for (cb = pt->docs; cb != NULL; cb = cb->next)
|
|
fputs(cb->frag, fp);
|
|
|
|
closeFile(fp);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the build file.
|
|
*/
|
|
static void generateBuildFile(sipSpec *pt, const char *buildFile,
|
|
const char *srcSuffix, const char *consModule)
|
|
{
|
|
const char *mname = pt->module->name;
|
|
FILE *fp;
|
|
|
|
fp = createFile(pt->module, buildFile, NULL);
|
|
|
|
prcode(fp, "target = %s\nsources =", mname);
|
|
|
|
if (isComposite(pt->module))
|
|
prcode(fp, " sip%scmodule.c", mname);
|
|
else if (isConsolidated(pt->module))
|
|
{
|
|
moduleDef *mod;
|
|
|
|
for (mod = pt->modules; mod != NULL; mod = mod->next)
|
|
if (mod->container == pt->module)
|
|
generateBuildFileSources(pt, mod, srcSuffix, fp);
|
|
|
|
prcode(fp, " sip%scmodule%s", mname, srcSuffix);
|
|
}
|
|
else if (consModule == NULL)
|
|
generateBuildFileSources(pt, pt->module, srcSuffix, fp);
|
|
else
|
|
prcode(fp, " sip%scmodule.c", mname);
|
|
|
|
if (isConsolidated(pt->module))
|
|
{
|
|
moduleDef *mod;
|
|
|
|
prcode(fp, "\nheaders =");
|
|
|
|
for (mod = pt->modules; mod != NULL; mod = mod->next)
|
|
if (mod->container == pt->module)
|
|
prcode(fp, " sipAPI%s.h", mod->name);
|
|
}
|
|
else if (!isComposite(pt->module) && consModule == NULL)
|
|
prcode(fp, "\nheaders = sipAPI%s.h", mname);
|
|
|
|
prcode(fp, "\n");
|
|
|
|
closeFile(fp);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the list of source files for a module.
|
|
*/
|
|
static void generateBuildFileSources(sipSpec *pt, moduleDef *mod,
|
|
const char *srcSuffix, FILE *fp)
|
|
{
|
|
const char *mname = mod->name;
|
|
|
|
if (mod->parts)
|
|
{
|
|
int p;
|
|
|
|
for (p = 0; p < mod->parts; ++p)
|
|
prcode(fp, " sip%spart%d%s", mname, p, srcSuffix);
|
|
}
|
|
else
|
|
{
|
|
ifaceFileDef *iff;
|
|
|
|
prcode(fp, " sip%scmodule%s", mname, srcSuffix);
|
|
|
|
for (iff = pt->ifacefiles; iff != NULL; iff = iff->next)
|
|
{
|
|
if (iff->module != mod)
|
|
continue;
|
|
|
|
if (iff->type == exception_iface)
|
|
continue;
|
|
|
|
if (iff->api_range != NULL)
|
|
prcode(fp, " sip%s%F_%d%s", mname, iff->fqcname, iff->api_range->index, srcSuffix);
|
|
else
|
|
prcode(fp, " sip%s%F%s", mname, iff->fqcname, srcSuffix);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate an expression in C++.
|
|
*/
|
|
void generateExpression(valueDef *vd, int in_str, FILE *fp)
|
|
{
|
|
while (vd != NULL)
|
|
{
|
|
if (vd->vunop != '\0')
|
|
prcode(fp,"%c",vd->vunop);
|
|
|
|
switch (vd->vtype)
|
|
{
|
|
case qchar_value:
|
|
prcode(fp,"'%c'",vd->u.vqchar);
|
|
break;
|
|
|
|
case string_value:
|
|
{
|
|
const char *quote = (in_str ? "\\\"" : "\"");
|
|
|
|
prcode(fp,"%s%s%s", quote, vd->u.vstr, quote);
|
|
}
|
|
|
|
break;
|
|
|
|
case numeric_value:
|
|
prcode(fp,"%l",vd->u.vnum);
|
|
break;
|
|
|
|
case real_value:
|
|
prcode(fp,"%g",vd->u.vreal);
|
|
break;
|
|
|
|
case scoped_value:
|
|
if (prcode_xml)
|
|
prScopedName(fp, vd->u.vscp, ".");
|
|
else
|
|
prcode(fp, "%S", vd->u.vscp);
|
|
|
|
break;
|
|
|
|
case fcall_value:
|
|
generateSimpleFunctionCall(vd->u.fcd,fp);
|
|
break;
|
|
}
|
|
|
|
if (vd->vbinop != '\0')
|
|
prcode(fp,"%c",vd->vbinop);
|
|
|
|
vd = vd->next;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the C++ internal module API header file.
|
|
*/
|
|
static void generateInternalAPIHeader(sipSpec *pt, moduleDef *mod,
|
|
const char *codeDir, stringList *xsl)
|
|
{
|
|
char *hfile;
|
|
const char *mname = mod->name;
|
|
int noIntro;
|
|
FILE *fp;
|
|
nameDef *nd;
|
|
moduleDef *imp;
|
|
moduleListDef *mld;
|
|
|
|
hfile = concat(codeDir, "/sipAPI", mname, ".h",NULL);
|
|
fp = createFile(mod, hfile, "Internal module API header file.");
|
|
|
|
/* Include files. */
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#ifndef _%sAPI_H\n"
|
|
"#define _%sAPI_H\n"
|
|
"\n"
|
|
"\n"
|
|
"#include <sip.h>\n"
|
|
, mname
|
|
, mname);
|
|
|
|
if (pluginPyTQt4(pt))
|
|
prcode(fp,
|
|
"\n"
|
|
"#include <TQMetaType>\n"
|
|
);
|
|
|
|
/* Define the enabled features. */
|
|
noIntro = TRUE;
|
|
|
|
for (imp = pt->modules; imp != NULL; imp = imp->next)
|
|
{
|
|
qualDef *qd;
|
|
|
|
for (qd = imp->qualifiers; qd != NULL; qd = qd->next)
|
|
if (qd->qtype == feature_qualifier && !excludedFeature(xsl, qd))
|
|
{
|
|
if (noIntro)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"/* These are the features that are enabled. */\n"
|
|
);
|
|
|
|
noIntro = FALSE;
|
|
}
|
|
|
|
prcode(fp,
|
|
"#define SIP_FEATURE_%s\n"
|
|
, qd->name);
|
|
}
|
|
}
|
|
|
|
if (!noIntro)
|
|
prcode(fp,
|
|
"\n"
|
|
);
|
|
|
|
generateCppCodeBlock(pt->exphdrcode, fp);
|
|
generateCppCodeBlock(mod->hdrcode, fp);
|
|
|
|
/* Shortcuts that hide the messy detail of the APIs. */
|
|
noIntro = TRUE;
|
|
|
|
for (nd = pt->namecache; nd != NULL; nd = nd->next)
|
|
{
|
|
if (!isUsedName(nd))
|
|
continue;
|
|
|
|
if (noIntro)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"/*\n"
|
|
" * Convenient names to refer to various strings defined in this module.\n"
|
|
" * Only the class names are part of the public API.\n"
|
|
" */\n"
|
|
);
|
|
|
|
noIntro = FALSE;
|
|
}
|
|
|
|
prcode(fp,
|
|
"#define %n %d\n"
|
|
"#define %N &sipStrings_%s[%d]\n"
|
|
, nd, (int)nd->offset
|
|
, nd, pt->module->name, (int)nd->offset);
|
|
}
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#define sipMalloc sipAPI_%s->api_malloc\n"
|
|
"#define sipFree sipAPI_%s->api_free\n"
|
|
"#define sipBuildResult sipAPI_%s->api_build_result\n"
|
|
"#define sipCallMethod sipAPI_%s->api_call_method\n"
|
|
"#define sipParseResult sipAPI_%s->api_parse_result\n"
|
|
"#define sipParseArgs sipAPI_%s->api_parse_args\n"
|
|
"#define sipParseKwdArgs sipAPI_%s->api_parse_kwd_args\n"
|
|
"#define sipParsePair sipAPI_%s->api_parse_pair\n"
|
|
"#define sipCommonDtor sipAPI_%s->api_common_dtor\n"
|
|
"#define sipConvertFromSequenceIndex sipAPI_%s->api_convert_from_sequence_index\n"
|
|
"#define sipConvertFromVoidPtr sipAPI_%s->api_convert_from_void_ptr\n"
|
|
"#define sipConvertToVoidPtr sipAPI_%s->api_convert_to_void_ptr\n"
|
|
"#define sipAddException sipAPI_%s->api_add_exception\n"
|
|
"#define sipNoFunction sipAPI_%s->api_no_function\n"
|
|
"#define sipNoMethod sipAPI_%s->api_no_method\n"
|
|
"#define sipAbstractMethod sipAPI_%s->api_abstract_method\n"
|
|
"#define sipBadClass sipAPI_%s->api_bad_class\n"
|
|
"#define sipBadCatcherResult sipAPI_%s->api_bad_catcher_result\n"
|
|
"#define sipBadCallableArg sipAPI_%s->api_bad_callable_arg\n"
|
|
"#define sipBadOperatorArg sipAPI_%s->api_bad_operator_arg\n"
|
|
"#define sipTrace sipAPI_%s->api_trace\n"
|
|
"#define sipTransferBack sipAPI_%s->api_transfer_back\n"
|
|
"#define sipTransferTo sipAPI_%s->api_transfer_to\n"
|
|
"#define sipTransferBreak sipAPI_%s->api_transfer_break\n"
|
|
"#define sipSimpleWrapper_Type sipAPI_%s->api_simplewrapper_type\n"
|
|
"#define sipWrapper_Type sipAPI_%s->api_wrapper_type\n"
|
|
"#define sipWrapperType_Type sipAPI_%s->api_wrappertype_type\n"
|
|
"#define sipVoidPtr_Type sipAPI_%s->api_voidptr_type\n"
|
|
"#define sipGetPyObject sipAPI_%s->api_get_pyobject\n"
|
|
"#define sipGetCppPtr sipAPI_%s->api_get_cpp_ptr\n"
|
|
"#define sipGetComplexCppPtr sipAPI_%s->api_get_complex_cpp_ptr\n"
|
|
"#define sipIsPyMethod sipAPI_%s->api_is_py_method\n"
|
|
"#define sipCallHook sipAPI_%s->api_call_hook\n"
|
|
"#define sipStartThread sipAPI_%s->api_start_thread\n"
|
|
"#define sipEndThread sipAPI_%s->api_end_thread\n"
|
|
"#define sipConnectRx sipAPI_%s->api_connect_rx\n"
|
|
"#define sipDisconnectRx sipAPI_%s->api_disconnect_rx\n"
|
|
"#define sipRaiseUnknownException sipAPI_%s->api_raise_unknown_exception\n"
|
|
"#define sipRaiseTypeException sipAPI_%s->api_raise_type_exception\n"
|
|
"#define sipBadLengthForSlice sipAPI_%s->api_bad_length_for_slice\n"
|
|
"#define sipAddTypeInstance sipAPI_%s->api_add_type_instance\n"
|
|
"#define sipGetAddress sipAPI_%s->api_get_address\n"
|
|
"#define sipFreeSipslot sipAPI_%s->api_free_sipslot\n"
|
|
"#define sipSameSlot sipAPI_%s->api_same_slot\n"
|
|
"#define sipPySlotExtend sipAPI_%s->api_pyslot_extend\n"
|
|
"#define sipConvertRx sipAPI_%s->api_convert_rx\n"
|
|
"#define sipAddDelayedDtor sipAPI_%s->api_add_delayed_dtor\n"
|
|
"#define sipCanConvertToType sipAPI_%s->api_can_convert_to_type\n"
|
|
"#define sipConvertToType sipAPI_%s->api_convert_to_type\n"
|
|
"#define sipForceConvertToType sipAPI_%s->api_force_convert_to_type\n"
|
|
"#define sipCanConvertToEnum sipAPI_%s->api_can_convert_to_enum\n"
|
|
"#define sipReleaseType sipAPI_%s->api_release_type\n"
|
|
"#define sipConvertFromType sipAPI_%s->api_convert_from_type\n"
|
|
"#define sipConvertFromNewType sipAPI_%s->api_convert_from_new_type\n"
|
|
"#define sipConvertFromEnum sipAPI_%s->api_convert_from_enum\n"
|
|
"#define sipGetState sipAPI_%s->api_get_state\n"
|
|
"#define sipLong_AsUnsignedLong sipAPI_%s->api_long_as_unsigned_long\n"
|
|
"#define sipExportSymbol sipAPI_%s->api_export_symbol\n"
|
|
"#define sipImportSymbol sipAPI_%s->api_import_symbol\n"
|
|
"#define sipFindType sipAPI_%s->api_find_type\n"
|
|
"#define sipFindNamedEnum sipAPI_%s->api_find_named_enum\n"
|
|
"#define sipBytes_AsChar sipAPI_%s->api_bytes_as_char\n"
|
|
"#define sipBytes_AsString sipAPI_%s->api_bytes_as_string\n"
|
|
"#define sipString_AsASCIIChar sipAPI_%s->api_string_as_ascii_char\n"
|
|
"#define sipString_AsASCIIString sipAPI_%s->api_string_as_ascii_string\n"
|
|
"#define sipString_AsLatin1Char sipAPI_%s->api_string_as_latin1_char\n"
|
|
"#define sipString_AsLatin1String sipAPI_%s->api_string_as_latin1_string\n"
|
|
"#define sipString_AsUTF8Char sipAPI_%s->api_string_as_utf8_char\n"
|
|
"#define sipString_AsUTF8String sipAPI_%s->api_string_as_utf8_string\n"
|
|
"#define sipUnicode_AsWChar sipAPI_%s->api_unicode_as_wchar\n"
|
|
"#define sipUnicode_AsWString sipAPI_%s->api_unicode_as_wstring\n"
|
|
"#define sipConvertFromConstVoidPtr sipAPI_%s->api_convert_from_const_void_ptr\n"
|
|
"#define sipConvertFromVoidPtrAndSize sipAPI_%s->api_convert_from_void_ptr_and_size\n"
|
|
"#define sipConvertFromConstVoidPtrAndSize sipAPI_%s->api_convert_from_const_void_ptr_and_size\n"
|
|
"#define sipInvokeSlot sipAPI_%s->api_invoke_slot\n"
|
|
"#define sipSaveSlot sipAPI_%s->api_save_slot\n"
|
|
"#define sipClearAnySlotReference sipAPI_%s->api_clear_any_slot_reference\n"
|
|
"#define sipVisitSlot sipAPI_%s->api_visit_slot\n"
|
|
"#define sipWrappedTypeName(wt) ((wt)->type->td_cname)\n"
|
|
"#define sipDeprecated sipAPI_%s->api_deprecated\n"
|
|
"#define sipKeepReference sipAPI_%s->api_keep_reference\n"
|
|
"#define sipRegisterPyType sipAPI_%s->api_register_py_type\n"
|
|
"#define sipTypeFromPyTypeObject sipAPI_%s->api_type_from_py_type_object\n"
|
|
"#define sipTypeScope sipAPI_%s->api_type_scope\n"
|
|
"#define sipResolveTypedef sipAPI_%s->api_resolve_typedef\n"
|
|
"#define sipRegisterAttributeGetter sipAPI_%s->api_register_attribute_getter\n"
|
|
"#define sipIsAPIEnabled sipAPI_%s->api_is_api_enabled\n"
|
|
"#define sipExportModule sipAPI_%s->api_export_module\n"
|
|
"#define sipInitModule sipAPI_%s->api_init_module\n"
|
|
"\n"
|
|
"/* These are deprecated. */\n"
|
|
"#define sipMapStringToClass sipAPI_%s->api_map_string_to_class\n"
|
|
"#define sipMapIntToClass sipAPI_%s->api_map_int_to_class\n"
|
|
"#define sipFindClass sipAPI_%s->api_find_class\n"
|
|
"#define sipFindMappedType sipAPI_%s->api_find_mapped_type\n"
|
|
"#define sipWrapper_Check(w) PyObject_TypeCheck((w), sipAPI_%s->api_wrapper_type)\n"
|
|
"#define sipGetWrapper(p, wt) sipGetPyObject((p), (wt)->type)\n"
|
|
"#define sipReleaseInstance(p, wt, s) sipReleaseType((p), (wt)->type, (s))\n"
|
|
"#define sipReleaseMappedType sipReleaseType\n"
|
|
"#define sipCanConvertToInstance(o, wt, f) sipCanConvertToType((o), (wt)->type, (f))\n"
|
|
"#define sipCanConvertToMappedType sipCanConvertToType\n"
|
|
"#define sipConvertToInstance(o, wt, t, f, s, e) sipConvertToType((o), (wt)->type, (t), (f), (s), (e))\n"
|
|
"#define sipConvertToMappedType sipConvertToType\n"
|
|
"#define sipForceConvertToInstance(o, wt, t, f, s, e) sipForceConvertToType((o), (wt)->type, (t), (f), (s), (e))\n"
|
|
"#define sipForceConvertToMappedType sipForceConvertToType\n"
|
|
"#define sipConvertFromInstance(p, wt, t) sipConvertFromType((p), (wt)->type, (t))\n"
|
|
"#define sipConvertFromMappedType sipConvertFromType\n"
|
|
"#define sipConvertFromNamedEnum(v, pt) sipConvertFromEnum((v), ((sipEnumTypeObject *)(pt))->type)\n"
|
|
"#define sipConvertFromNewInstance(p, wt, t) sipConvertFromNewType((p), (wt)->type, (t))\n"
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname
|
|
,mname);
|
|
|
|
/* The name strings. */
|
|
prcode(fp,
|
|
"\n"
|
|
"/* The strings used by this module. */\n"
|
|
"extern const char sipStrings_%s[];\n"
|
|
, pt->module->name);
|
|
|
|
/* The unscoped enum macros. */
|
|
generateEnumMacros(pt, mod, NULL, NULL, fp);
|
|
|
|
generateModuleAPI(pt, mod, fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"/* The SIP API, this module's API and the APIs of any imported modules. */\n"
|
|
"extern const sipAPIDef *sipAPI_%s;\n"
|
|
"extern sipExportedModuleDef sipModuleAPI_%s;\n"
|
|
, mname
|
|
, mname, mname);
|
|
|
|
for (mld = mod->allimports; mld != NULL; mld = mld->next)
|
|
{
|
|
generateImportedModuleAPI(pt, mod, mld->module, fp);
|
|
|
|
prcode(fp,
|
|
"extern const sipExportedModuleDef *sipModuleAPI_%s_%s;\n"
|
|
, mname, mld->module->name);
|
|
}
|
|
|
|
if (pluginPyTQt4(pt))
|
|
prcode(fp,
|
|
"\n"
|
|
"typedef const TQMetaObject *(*sip_qt_metaobject_func)(sipSimpleWrapper *,sipTypeDef *);\n"
|
|
"extern sip_qt_metaobject_func sip_%s_qt_metaobject;\n"
|
|
"\n"
|
|
"typedef int (*sip_qt_metacall_func)(sipSimpleWrapper *,sipTypeDef *,TQMetaObject::Call,int,void **);\n"
|
|
"extern sip_qt_metacall_func sip_%s_qt_metacall;\n"
|
|
"\n"
|
|
"typedef int (*sip_qt_metacast_func)(sipSimpleWrapper *,sipTypeDef *,const char *);\n"
|
|
"extern sip_qt_metacast_func sip_%s_qt_metacast;\n"
|
|
, mname
|
|
, mname
|
|
, mname);
|
|
|
|
/*
|
|
* Note that we don't forward declare the virtual handlers. This is
|
|
* because we would need to #include everything needed for their argument
|
|
* types.
|
|
*/
|
|
prcode(fp,
|
|
"\n"
|
|
"#endif\n"
|
|
);
|
|
|
|
closeFile(fp);
|
|
free(hfile);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the filename of a source code part on the heap.
|
|
*/
|
|
static char *makePartName(const char *codeDir, const char *mname, int part,
|
|
const char *srcSuffix)
|
|
{
|
|
char buf[50];
|
|
|
|
sprintf(buf, "part%d", part);
|
|
|
|
return concat(codeDir, "/sip", mname, buf, srcSuffix, NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the C code for a composite module.
|
|
*/
|
|
static void generateCompositeCpp(sipSpec *pt, const char *codeDir)
|
|
{
|
|
char *cppfile;
|
|
moduleDef *mod;
|
|
FILE *fp;
|
|
|
|
cppfile = concat(codeDir, "/sip", pt->module->name, "cmodule.c", NULL);
|
|
fp = createCompilationUnit(pt->module, cppfile, "Composite module code.");
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#include <Python.h>\n"
|
|
"\n"
|
|
"\n"
|
|
"static void sip_import_component_module(PyObject *d, const char *name)\n"
|
|
"{\n"
|
|
"#if PY_VERSION_HEX >= 0x02050000\n"
|
|
" PyObject *mod = PyImport_ImportModule(name);\n"
|
|
"#else\n"
|
|
" PyObject *mod = PyImport_ImportModule((char *)name);\n"
|
|
"#endif\n"
|
|
"\n"
|
|
" /*\n"
|
|
" * Note that we don't complain if the module can't be imported. This\n"
|
|
" * is a favour to Linux distro packagers who like to split PyTQt into\n"
|
|
" * different sub-packages.\n"
|
|
" */\n"
|
|
" if (mod)\n"
|
|
" {\n"
|
|
" PyDict_Merge(d, PyModule_GetDict(mod), 0);\n"
|
|
" Py_DECREF(mod);\n"
|
|
" }\n"
|
|
"}\n"
|
|
);
|
|
|
|
generateModInitStart(pt->module, TRUE, fp);
|
|
generateModDefinition(pt->module, "NULL", fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
" PyObject *sipModule, *sipModuleDict;\n"
|
|
"\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" sipModule = PyModule_Create(&sip_module_def);\n"
|
|
"#else\n"
|
|
" sipModule = Py_InitModule(\"%s\", 0);\n"
|
|
"#endif\n"
|
|
"\n"
|
|
" if (sipModule == NULL)\n"
|
|
" SIP_MODULE_RETURN(NULL);\n"
|
|
"\n"
|
|
" sipModuleDict = PyModule_GetDict(sipModule);\n"
|
|
"\n"
|
|
, pt->module->fullname->text);
|
|
|
|
for (mod = pt->modules; mod != NULL; mod = mod->next)
|
|
if (mod->container == pt->module)
|
|
prcode(fp,
|
|
" sip_import_component_module(sipModuleDict, \"%s\");\n"
|
|
, mod->fullname->text);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
" PyErr_Clear();\n"
|
|
"\n"
|
|
" SIP_MODULE_RETURN(sipModule);\n"
|
|
"}\n"
|
|
);
|
|
|
|
closeFile(fp);
|
|
free(cppfile);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the C/C++ code for a consolidated module.
|
|
*/
|
|
static void generateConsolidatedCpp(sipSpec *pt, const char *codeDir,
|
|
const char *srcSuffix)
|
|
{
|
|
char *cppfile;
|
|
const char *mname = pt->module->name;
|
|
moduleDef *mod;
|
|
FILE *fp;
|
|
|
|
cppfile = concat(codeDir, "/sip", mname, "cmodule", srcSuffix, NULL);
|
|
fp = createCompilationUnit(pt->module, cppfile, "Consolidated module code.");
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#include <Python.h>\n"
|
|
"#include <string.h>\n"
|
|
"#include <sip.h>\n"
|
|
);
|
|
|
|
generateNameCache(pt, fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* The component module initialisers. */\n"
|
|
);
|
|
|
|
/* Declare the component module initialisers. */
|
|
for (mod = pt->modules; mod != NULL; mod = mod->next)
|
|
if (mod->container == pt->module)
|
|
prcode(fp,
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
"extern PyObject *sip_init_%s(void);\n"
|
|
"#else\n"
|
|
"extern void sip_init_%s(void);\n"
|
|
"#endif\n"
|
|
, mod->name
|
|
, mod->name);
|
|
|
|
/* Generate the init function. */
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
);
|
|
|
|
if (!generating_c)
|
|
prcode(fp,
|
|
"extern \"C\" {static PyObject *sip_init(PyObject *, PyObject *);}\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
"static PyObject *sip_init(PyObject *%s, PyObject *arg)\n"
|
|
"{\n"
|
|
" struct component {\n"
|
|
" const char *name;\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" PyObject *(*init)(void);\n"
|
|
"#else\n"
|
|
" void (*init)(void);\n"
|
|
"#endif\n"
|
|
" };\n"
|
|
"\n"
|
|
" static struct component components[] = {\n"
|
|
, (generating_c ? "self" : ""));
|
|
|
|
for (mod = pt->modules; mod != NULL; mod = mod->next)
|
|
if (mod->container == pt->module)
|
|
prcode(fp,
|
|
" {\"%s\", sip_init_%s},\n"
|
|
, mod->fullname->text, mod->name);
|
|
|
|
prcode(fp,
|
|
" {NULL, NULL}\n"
|
|
" };\n"
|
|
"\n"
|
|
" const char *name;\n"
|
|
" struct component *scd;\n"
|
|
"\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" name = PyBytes_AsString(arg);\n"
|
|
"#else\n"
|
|
" name = PyString_AsString(arg);\n"
|
|
"#endif\n"
|
|
"\n"
|
|
" if (name == NULL)\n"
|
|
" return NULL;\n"
|
|
"\n"
|
|
" for (scd = components; scd->name != NULL; ++scd)\n"
|
|
" if (strcmp(scd->name, name) == 0)\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" return (*scd->init)();\n"
|
|
"#else\n"
|
|
" {\n"
|
|
" (*scd->init)();\n"
|
|
"\n"
|
|
" Py_INCREF(Py_None);\n"
|
|
" return Py_None;\n"
|
|
" }\n"
|
|
"#endif\n"
|
|
"\n"
|
|
" PyErr_Format(PyExc_ImportError, \"unknown component module %%s\", name);\n"
|
|
"\n"
|
|
" return NULL;\n"
|
|
"}\n"
|
|
);
|
|
|
|
generateModInitStart(pt->module, generating_c, fp);
|
|
|
|
prcode(fp,
|
|
" static PyMethodDef sip_methods[] = {\n"
|
|
" {SIP_MLNAME_CAST(\"init\"), sip_init, METH_O, NULL},\n"
|
|
" {NULL, NULL, 0, NULL}\n"
|
|
" };\n"
|
|
);
|
|
|
|
generateModDefinition(pt->module, "sip_methods", fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" return PyModule_Create(&sip_module_def);\n"
|
|
"#else\n"
|
|
" Py_InitModule(\"%s\", sip_methods);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
, mname);
|
|
|
|
closeFile(fp);
|
|
free(cppfile);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the C/C++ code for a component module.
|
|
*/
|
|
static void generateComponentCpp(sipSpec *pt, const char *codeDir,
|
|
const char *consModule)
|
|
{
|
|
char *cppfile;
|
|
FILE *fp;
|
|
|
|
cppfile = concat(codeDir, "/sip", pt->module->name, "cmodule.c", NULL);
|
|
fp = createCompilationUnit(pt->module, cppfile, "Component module code.");
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#include <Python.h>\n"
|
|
);
|
|
|
|
generateModInitStart(pt->module, TRUE, fp);
|
|
generateModDefinition(pt->module, "NULL", fp);
|
|
|
|
prcode(fp,
|
|
" PyObject *sip_mod, *sip_result;\n"
|
|
"\n"
|
|
" /* Import the consolidated module. */\n"
|
|
" if ((sip_mod = PyImport_ImportModule(\"%s\")) == NULL)\n"
|
|
" SIP_MODULE_RETURN(NULL);\n"
|
|
"\n"
|
|
, consModule);
|
|
|
|
prcode(fp,
|
|
" /* Ask the consolidated module to do the initialistion. */\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" sip_result = PyObject_CallMethod(sip_mod, \"init\", \"y\", \"%s\");\n"
|
|
"#else\n"
|
|
" sip_result = PyObject_CallMethod(sip_mod, \"init\", \"s\", \"%s\");\n"
|
|
"#endif\n"
|
|
" Py_DECREF(sip_mod);\n"
|
|
"\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" return sip_result;\n"
|
|
"#else\n"
|
|
" Py_XDECREF(sip_result);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
, pt->module->fullname->text
|
|
, pt->module->fullname->text);
|
|
|
|
closeFile(fp);
|
|
free(cppfile);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the name cache definition.
|
|
*/
|
|
static void generateNameCache(sipSpec *pt, FILE *fp)
|
|
{
|
|
nameDef *nd;
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"/* Define the strings used by this module. */\n"
|
|
);
|
|
|
|
if (isConsolidated(pt->module))
|
|
prcode(fp,
|
|
"extern const char sipStrings_%s[];\n"
|
|
, pt->module->name);
|
|
|
|
prcode(fp,
|
|
"const char sipStrings_%s[] = {\n"
|
|
, pt->module->name);
|
|
|
|
for (nd = pt->namecache; nd != NULL; nd = nd->next)
|
|
{
|
|
const char *cp;
|
|
|
|
if (!isUsedName(nd) || isSubstring(nd))
|
|
continue;
|
|
|
|
prcode(fp, " ");
|
|
|
|
for (cp = nd->text; *cp != '\0'; ++cp)
|
|
prcode(fp, "'%c', ", *cp);
|
|
|
|
prcode(fp, "0,\n");
|
|
}
|
|
|
|
prcode(fp, "};\n");
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the C/C++ code.
|
|
*/
|
|
static void generateCpp(sipSpec *pt, moduleDef *mod, const char *codeDir,
|
|
const char *srcSuffix, int parts, stringList *xsl)
|
|
{
|
|
char *cppfile;
|
|
const char *mname = mod->name;
|
|
int nrSccs = 0, files_in_part, max_per_part, this_part, mod_nr, enum_idx;
|
|
int is_inst_class, is_inst_voidp, is_inst_char, is_inst_string;
|
|
int is_inst_int, is_inst_long, is_inst_ulong, is_inst_longlong;
|
|
int is_inst_ulonglong, is_inst_double, nr_enummembers, is_api_versions;
|
|
int is_versioned_functions;
|
|
int hasexternal = FALSE, slot_extenders = FALSE, ctor_extenders = FALSE;
|
|
FILE *fp;
|
|
moduleListDef *mld;
|
|
classDef *cd;
|
|
memberDef *md;
|
|
enumDef *ed;
|
|
ifaceFileDef *iff;
|
|
virtHandlerDef *vhd;
|
|
exceptionDef *xd;
|
|
|
|
/* Calculate the number of files in each part. */
|
|
if (parts)
|
|
{
|
|
int nr_files = 1;
|
|
|
|
for (iff = pt->ifacefiles; iff != NULL; iff = iff->next)
|
|
if (iff->module == mod && iff->type != exception_iface)
|
|
++nr_files;
|
|
|
|
max_per_part = (nr_files + parts - 1) / parts;
|
|
files_in_part = 1;
|
|
this_part = 0;
|
|
|
|
cppfile = makePartName(codeDir, mname, 0, srcSuffix);
|
|
}
|
|
else
|
|
cppfile = concat(codeDir, "/sip", mname, "cmodule", srcSuffix, NULL);
|
|
|
|
fp = createCompilationUnit(mod, cppfile, "Module code.");
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#include \"sipAPI%s.h\"\n"
|
|
, mname);
|
|
|
|
/*
|
|
* Include the library headers for types used by virtual handlers, module
|
|
* level functions, module level variables and TQt meta types.
|
|
*/
|
|
generateUsedIncludes(mod->used, fp);
|
|
|
|
/*
|
|
* If there should be a TQt support API then generate stubs values for the
|
|
* optional parts. These should be undefined in %ModuleCode if a C++
|
|
* implementation is provided.
|
|
*/
|
|
if (mod->qobjclass >= 0)
|
|
prcode(fp,
|
|
"\n"
|
|
"#define sipTQtCreateUniversalSignal 0\n"
|
|
"#define sipTQtFindUniversalSignal 0\n"
|
|
"#define sipTQtEmitSignal 0\n"
|
|
"#define sipTQtConnectPySignal 0\n"
|
|
"#define sipTQtDisconnectPySignal 0\n"
|
|
);
|
|
|
|
/* Define the names. */
|
|
if (mod->container == NULL)
|
|
generateNameCache(pt, fp);
|
|
|
|
/* Generate the C++ code blocks. */
|
|
generateCppCodeBlock(mod->cppcode, fp);
|
|
|
|
/* Generate any virtual handler declarations. */
|
|
for (vhd = mod->virthandlers; vhd != NULL; vhd = vhd->next)
|
|
if (!isDuplicateVH(vhd))
|
|
generateVirtualHandler(vhd, fp);
|
|
|
|
/* Generate the global functions. */
|
|
for (md = mod->othfuncs; md != NULL; md = md->next)
|
|
if (md->slot == no_slot)
|
|
generateOrdinaryFunction(pt, mod, NULL, NULL, md, fp);
|
|
else
|
|
{
|
|
overDef *od;
|
|
|
|
/*
|
|
* Make sure that there is still an overload and we haven't moved
|
|
* them all to classes.
|
|
*/
|
|
for (od = mod->overs; od != NULL; od = od->next)
|
|
if (od->common == md)
|
|
{
|
|
generateSlot(mod, NULL, NULL, md, fp);
|
|
slot_extenders = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Generate any class specific ctor or slot extenders. */
|
|
for (cd = mod->proxies; cd != NULL; cd = cd->next)
|
|
{
|
|
if (cd->ctors != NULL)
|
|
{
|
|
generateTypeInit(cd, mod, fp);
|
|
ctor_extenders = TRUE;
|
|
}
|
|
|
|
for (md = cd->members; md != NULL; md = md->next)
|
|
{
|
|
generateSlot(mod, cd, NULL, md, fp);
|
|
slot_extenders = TRUE;
|
|
}
|
|
}
|
|
|
|
/* Generate any ctor extender table. */
|
|
if (ctor_extenders)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"static sipInitExtenderDef initExtenders[] = {\n"
|
|
);
|
|
|
|
for (cd = mod->proxies; cd != NULL; cd = cd->next)
|
|
if (cd->ctors != NULL)
|
|
{
|
|
prcode(fp,
|
|
" {%P, init_%L, ", cd->iff->api_range, cd->iff);
|
|
|
|
generateEncodedType(mod, cd, 0, fp);
|
|
|
|
prcode(fp, ", NULL},\n"
|
|
);
|
|
}
|
|
|
|
prcode(fp,
|
|
" {-1, NULL, {0, 0, 0}, NULL}\n"
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
/* Generate any slot extender table. */
|
|
if (slot_extenders)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"static sipPySlotExtenderDef slotExtenders[] = {\n"
|
|
);
|
|
|
|
for (md = mod->othfuncs; md != NULL; md = md->next)
|
|
{
|
|
overDef *od;
|
|
|
|
if (md->slot == no_slot)
|
|
continue;
|
|
|
|
for (od = mod->overs; od != NULL; od = od->next)
|
|
if (od->common == md)
|
|
{
|
|
if (py2OnlySlot(md->slot))
|
|
prcode(fp,
|
|
"#if PY_MAJOR_VERSION < 3\n"
|
|
);
|
|
else if (py2_5LaterSlot(md->slot))
|
|
prcode(fp,
|
|
"#if PY_VERSION_HEX >= 0x02050000\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
" {(void *)slot_%s, %s, {0, 0, 0}},\n"
|
|
, md->pyname->text, slotName(md->slot));
|
|
|
|
if (py2OnlySlot(md->slot) || py2_5LaterSlot(md->slot))
|
|
prcode(fp,
|
|
"#endif\n"
|
|
);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (cd = mod->proxies; cd != NULL; cd = cd->next)
|
|
for (md = cd->members; md != NULL; md = md->next)
|
|
{
|
|
if (py2OnlySlot(md->slot))
|
|
prcode(fp,
|
|
"#if PY_MAJOR_VERSION < 3\n"
|
|
);
|
|
else if (py2_5LaterSlot(md->slot))
|
|
prcode(fp,
|
|
"#if PY_VERSION_HEX >= 0x02050000\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
" {(void *)slot_%L_%s, %s, ", cd->iff, md->pyname->text, slotName(md->slot));
|
|
|
|
generateEncodedType(mod, cd, 0, fp);
|
|
|
|
prcode(fp, "},\n"
|
|
);
|
|
|
|
if (py2OnlySlot(md->slot) || py2_5LaterSlot(md->slot))
|
|
prcode(fp,
|
|
"#endif\n"
|
|
);
|
|
}
|
|
|
|
prcode(fp,
|
|
" {NULL, (sipPySlotType)0, {0, 0, 0}}\n"
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
/* Generate the global access functions. */
|
|
generateAccessFunctions(pt, mod, NULL, fp);
|
|
|
|
/* Generate any sub-class convertors. */
|
|
nrSccs = generateSubClassConvertors(pt, mod, fp);
|
|
|
|
/* Generate the external classes table if needed. */
|
|
for (cd = pt->classes; cd != NULL; cd = cd->next)
|
|
{
|
|
if (!isExternal(cd))
|
|
continue;
|
|
|
|
if (cd->iff->module != mod)
|
|
continue;
|
|
|
|
if (!hasexternal)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines each external type declared in this module, */\n"
|
|
"static sipExternalTypeDef externalTypesTable[] = {\n"
|
|
);
|
|
|
|
hasexternal = TRUE;
|
|
}
|
|
|
|
prcode(fp,
|
|
" {%d, \"", cd->iff->ifacenr);
|
|
prScopedName(fp, classFTQCName(cd), ".");
|
|
prcode(fp,"\"},\n"
|
|
);
|
|
}
|
|
|
|
if (hasexternal)
|
|
prcode(fp,
|
|
" {-1, NULL}\n"
|
|
"};\n"
|
|
);
|
|
|
|
/* Generate any enum slot tables. */
|
|
for (ed = pt->enums; ed != NULL; ed = ed->next)
|
|
{
|
|
memberDef *slot;
|
|
|
|
if (ed->module != mod || ed->fqcname == NULL)
|
|
continue;
|
|
|
|
if (ed->slots == NULL)
|
|
continue;
|
|
|
|
for (slot = ed->slots; slot != NULL; slot = slot->next)
|
|
generateSlot(mod, NULL, ed, slot, fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"static sipPySlotDef slots_%C[] = {\n"
|
|
, ed->fqcname);
|
|
|
|
for (slot = ed->slots; slot != NULL; slot = slot->next)
|
|
{
|
|
const char *stype;
|
|
|
|
if ((stype = slotName(slot->slot)) != NULL)
|
|
{
|
|
if (py2OnlySlot(slot->slot))
|
|
prcode(fp,
|
|
"#if PY_MAJOR_VERSION < 3\n"
|
|
);
|
|
else if (py2_5LaterSlot(slot->slot))
|
|
prcode(fp,
|
|
"#if PY_VERSION_HEX >= 0x02050000\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
" {(void *)slot_%C_%s, %s},\n"
|
|
, ed->fqcname, slot->pyname->text, stype);
|
|
|
|
if (py2OnlySlot(slot->slot) || py2_5LaterSlot(slot->slot))
|
|
prcode(fp,
|
|
"#endif\n"
|
|
);
|
|
}
|
|
}
|
|
|
|
prcode(fp,
|
|
" {0, (sipPySlotType)0}\n"
|
|
"};\n"
|
|
"\n"
|
|
);
|
|
}
|
|
|
|
/* Generate the enum type structures. */
|
|
enum_idx = 0;
|
|
|
|
for (ed = pt->enums; ed != NULL; ed = ed->next)
|
|
{
|
|
int type_nr = -1;
|
|
apiVersionRangeDef *avr = NULL;
|
|
|
|
if (ed->module != mod || ed->fqcname == NULL)
|
|
continue;
|
|
|
|
if (ed->ecd != NULL)
|
|
{
|
|
if (isTemplateClass(ed->ecd))
|
|
continue;
|
|
|
|
type_nr = ed->ecd->iff->first_alt->ifacenr;
|
|
avr = ed->ecd->iff->api_range;
|
|
}
|
|
else if (ed->emtd != NULL)
|
|
{
|
|
type_nr = ed->emtd->iff->first_alt->ifacenr;
|
|
avr = ed->emtd->iff->api_range;
|
|
}
|
|
|
|
if (enum_idx == 0)
|
|
{
|
|
prcode(fp,
|
|
"static sipEnumTypeDef enumTypes[] = {\n"
|
|
);
|
|
}
|
|
|
|
ed->enum_idx = enum_idx++;
|
|
|
|
prcode(fp,
|
|
" {{%P, ", avr);
|
|
|
|
if (ed->next_alt != NULL)
|
|
prcode(fp, "&enumTypes[%d].etd_base", ed->next_alt->enum_idx);
|
|
else
|
|
prcode(fp, "0");
|
|
|
|
prcode(fp, ", 0, SIP_TYPE_ENUM, %n, {0}}, %n, %d, ", ed->cname, ed->pyname, type_nr);
|
|
|
|
if (ed->slots != NULL)
|
|
prcode(fp, "slots_%C", ed->fqcname);
|
|
else
|
|
prcode(fp, "NULL");
|
|
|
|
prcode(fp, "},\n"
|
|
);
|
|
}
|
|
|
|
if (enum_idx != 0)
|
|
prcode(fp,
|
|
"};\n"
|
|
);
|
|
|
|
nr_enummembers = generateEnumMemberTable(pt, mod, NULL, NULL, fp);
|
|
|
|
/* Generate the types table. */
|
|
if (mod->nrtypes > 0)
|
|
generateTypesTable(pt, mod, fp);
|
|
|
|
if (mod->nrtypedefs > 0)
|
|
{
|
|
typedefDef *td;
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/*\n"
|
|
" * These define each typedef in this module.\n"
|
|
" */\n"
|
|
"static sipTypedefDef typedefsTable[] = {\n"
|
|
);
|
|
|
|
for (td = pt->typedefs; td != NULL; td = td->next)
|
|
{
|
|
if (td->module != mod)
|
|
continue;
|
|
|
|
prcode(fp,
|
|
" {\"%S\", \"", td->fqname);
|
|
|
|
/* The default behaviour isn't right in a couple of cases. */
|
|
if (td->type.atype == longlong_type)
|
|
prcode(fp, "long long");
|
|
else if (td->type.atype == ulonglong_type)
|
|
prcode(fp, "unsigned long long");
|
|
else
|
|
prcode(fp, "%b", &td->type);
|
|
|
|
prcode(fp, "\"},\n"
|
|
);
|
|
}
|
|
|
|
prcode(fp,
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
if (mod->nrvirthandlers > 0)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/*\n"
|
|
" * This defines the virtual handlers that this module implements and can be\n"
|
|
" * used by other modules.\n"
|
|
" */\n"
|
|
"static sipVirtHandlerFunc virtHandlersTable[] = {\n"
|
|
);
|
|
|
|
for (vhd = mod->virthandlers; vhd != NULL; vhd = vhd->next)
|
|
if (!isDuplicateVH(vhd))
|
|
prcode(fp,
|
|
" (sipVirtHandlerFunc)sipVH_%s_%d,\n"
|
|
, mname, vhd->virthandlernr);
|
|
|
|
prcode(fp,
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
if (mod->allimports != NULL)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines the modules that this module needs to import. */\n"
|
|
"static sipImportedModuleDef importsTable[] = {\n"
|
|
);
|
|
|
|
for (mld = mod->allimports; mld != NULL; mld = mld->next)
|
|
prcode(fp,
|
|
" {\"%s\", %d, NULL},\n"
|
|
, mld->module->fullname->text, mld->module->version);
|
|
|
|
prcode(fp,
|
|
" {NULL, -1, NULL}\n"
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
if (nrSccs > 0)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines the class sub-convertors that this module defines. */\n"
|
|
"static sipSubClassConvertorDef convertorsTable[] = {\n"
|
|
);
|
|
|
|
for (cd = pt->classes; cd != NULL; cd = cd->next)
|
|
{
|
|
if (cd->iff->module != mod)
|
|
continue;
|
|
|
|
if (cd->convtosubcode == NULL)
|
|
continue;
|
|
|
|
prcode(fp,
|
|
" {sipSubClass_%C, ",classFTQCName(cd));
|
|
|
|
generateEncodedType(mod, cd->subbase, 0, fp);
|
|
|
|
prcode(fp,", NULL},\n");
|
|
}
|
|
|
|
prcode(fp,
|
|
" {NULL, {0, 0, 0}, NULL}\n"
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
/* Generate any license information. */
|
|
if (mod->license != NULL)
|
|
{
|
|
licenseDef *ld = mod->license;
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* Define the module's license. */\n"
|
|
"static sipLicenseDef module_license = {\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
" \"%s\",\n"
|
|
, ld->type);
|
|
|
|
if (ld->licensee != NULL)
|
|
prcode(fp,
|
|
" \"%s\",\n"
|
|
, ld->licensee);
|
|
else
|
|
prcode(fp,
|
|
" NULL,\n"
|
|
);
|
|
|
|
if (ld->timestamp != NULL)
|
|
prcode(fp,
|
|
" \"%s\",\n"
|
|
, ld->timestamp);
|
|
else
|
|
prcode(fp,
|
|
" NULL,\n"
|
|
);
|
|
|
|
if (ld->sig != NULL)
|
|
prcode(fp,
|
|
" \"%s\"\n"
|
|
, ld->sig);
|
|
else
|
|
prcode(fp,
|
|
" NULL\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
/* Generate each instance table. */
|
|
is_inst_class = generateClasses(pt, mod, NULL, fp);
|
|
is_inst_voidp = generateVoidPointers(pt, mod, NULL, fp);
|
|
is_inst_char = generateChars(pt, mod, NULL, fp);
|
|
is_inst_string = generateStrings(pt, mod, NULL, fp);
|
|
is_inst_int = generateInts(pt, mod, NULL, fp);
|
|
is_inst_long = generateLongs(pt, mod, NULL, fp);
|
|
is_inst_ulong = generateUnsignedLongs(pt, mod, NULL, fp);
|
|
is_inst_longlong = generateLongLongs(pt, mod, NULL, fp);
|
|
is_inst_ulonglong = generateUnsignedLongLongs(pt, mod, NULL, fp);
|
|
is_inst_double = generateDoubles(pt, mod, NULL, fp);
|
|
|
|
/* Generate any exceptions table. */
|
|
if (mod->nrexceptions > 0)
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"static PyObject *exceptionsTable[%d];\n"
|
|
, mod->nrexceptions);
|
|
|
|
/* Generate any API versions table. */
|
|
if (mod->api_ranges != NULL || mod->api_versions != NULL)
|
|
{
|
|
apiVersionRangeDef *avr;
|
|
|
|
is_api_versions = TRUE;
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines the API versions and ranges in use. */\n"
|
|
"static int apiVersions[] = {");
|
|
|
|
for (avr = mod->api_ranges; avr != NULL; avr = avr->next)
|
|
prcode(fp, "%n, %d, %d, ", avr->api_name, avr->from, avr->to);
|
|
|
|
for (avr = mod->api_versions; avr != NULL; avr = avr->next)
|
|
prcode(fp, "%n, %d, -1, ", avr->api_name, avr->from);
|
|
|
|
prcode(fp, "-1};\n"
|
|
);
|
|
}
|
|
else
|
|
is_api_versions = FALSE;
|
|
|
|
/* Generate any versioned global functions. */
|
|
is_versioned_functions = FALSE;
|
|
|
|
for (md = mod->othfuncs; md != NULL; md = md->next)
|
|
if (md->slot == no_slot)
|
|
{
|
|
overDef *od;
|
|
int has_docstring;
|
|
|
|
if (notVersioned(md))
|
|
continue;
|
|
|
|
if (!is_versioned_functions)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines the global functions where all overloads are versioned. */\n"
|
|
"static sipVersionedFunctionDef versionedFunctions[] = {\n"
|
|
);
|
|
|
|
is_versioned_functions = TRUE;
|
|
}
|
|
|
|
has_docstring = FALSE;
|
|
|
|
if (md->docstring != NULL || (docstrings && hasDocstring(pt, mod->overs, md, NULL)))
|
|
has_docstring = TRUE;
|
|
|
|
/*
|
|
* Every overload has an entry to capture all the version ranges.
|
|
*/
|
|
for (od = mod->overs; od != NULL; od = od->next)
|
|
{
|
|
if (od->common != md)
|
|
continue;
|
|
|
|
prcode(fp,
|
|
" {%n, ", md->pyname);
|
|
|
|
if (noArgParser(md) || useKeywordArgsFunction(md))
|
|
prcode(fp, "(PyCFunction)func_%s, METH_VARARGS|METH_KEYWORDS", md->pyname->text);
|
|
else
|
|
prcode(fp, "func_%s, METH_VARARGS", md->pyname->text);
|
|
|
|
if (has_docstring)
|
|
prcode(fp, ", doc_%s", md->pyname->text);
|
|
else
|
|
prcode(fp, ", NULL");
|
|
|
|
prcode(fp, ", %P},\n"
|
|
, od->api_range);
|
|
}
|
|
}
|
|
|
|
if (is_versioned_functions)
|
|
prcode(fp,
|
|
" {-1, 0, 0, 0, -1}\n"
|
|
"};\n"
|
|
);
|
|
|
|
/* Generate any TQt support API. */
|
|
if (mod->qobjclass >= 0)
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines the TQt support API. */\n"
|
|
"\n"
|
|
"static sipTQtAPI qtAPI = {\n"
|
|
" &typesTable[%d],\n"
|
|
" sipTQtCreateUniversalSignal,\n"
|
|
" sipTQtFindUniversalSignal,\n"
|
|
" sipTQtCreateUniversalSlot,\n"
|
|
" sipTQtDestroyUniversalSlot,\n"
|
|
" sipTQtFindSlot,\n"
|
|
" sipTQtConnect,\n"
|
|
" sipTQtDisconnect,\n"
|
|
" sipTQtSameSignalSlotName,\n"
|
|
" sipTQtFindSipslot,\n"
|
|
" sipTQtEmitSignal,\n"
|
|
" sipTQtConnectPySignal,\n"
|
|
" sipTQtDisconnectPySignal\n"
|
|
"};\n"
|
|
, mod->qobjclass);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* This defines this module. */\n"
|
|
"sipExportedModuleDef sipModuleAPI_%s = {\n"
|
|
" 0,\n"
|
|
" SIP_API_MINOR_NR,\n"
|
|
" %n,\n"
|
|
" 0,\n"
|
|
" %d,\n"
|
|
" sipStrings_%s,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" %d,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" %d,\n"
|
|
" %s,\n"
|
|
" %d,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" {%s, %s, %s, %s, %s, %s, %s, %s, %s, %s},\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" %s,\n"
|
|
" NULL,\n"
|
|
" %s,\n"
|
|
" %s\n"
|
|
"};\n"
|
|
, mname
|
|
, mod->fullname
|
|
, mod->version
|
|
, pt->module->name
|
|
, mod->allimports != NULL ? "importsTable" : "NULL"
|
|
, mod->qobjclass >= 0 ? "&qtAPI" : "NULL"
|
|
, mod->nrtypes
|
|
, mod->nrtypes > 0 ? "typesTable" : "NULL"
|
|
, hasexternal ? "externalTypesTable" : "NULL"
|
|
, nr_enummembers
|
|
, nr_enummembers > 0 ? "enummembers" : "NULL"
|
|
, mod->nrtypedefs
|
|
, mod->nrtypedefs > 0 ? "typedefsTable" : "NULL"
|
|
, mod->nrvirthandlers > 0 ? "virtHandlersTable" : "NULL"
|
|
, nrSccs > 0 ? "convertorsTable" : "NULL"
|
|
, is_inst_class ? "typeInstances" : "NULL"
|
|
, is_inst_voidp ? "voidPtrInstances" : "NULL"
|
|
, is_inst_char ? "charInstances" : "NULL"
|
|
, is_inst_string ? "stringInstances" : "NULL"
|
|
, is_inst_int ? "intInstances" : "NULL"
|
|
, is_inst_long ? "longInstances" : "NULL"
|
|
, is_inst_ulong ? "unsignedLongInstances" : "NULL"
|
|
, is_inst_longlong ? "longLongInstances" : "NULL"
|
|
, is_inst_ulonglong ? "unsignedLongLongInstances" : "NULL"
|
|
, is_inst_double ? "doubleInstances" : "NULL"
|
|
, mod->license != NULL ? "&module_license" : "NULL"
|
|
, mod->nrexceptions > 0 ? "exceptionsTable" : "NULL"
|
|
, slot_extenders ? "slotExtenders" : "NULL"
|
|
, ctor_extenders ? "initExtenders" : "NULL"
|
|
, hasDelayedDtors(mod) ? "sipDelayedDtors" : "NULL"
|
|
, is_api_versions ? "apiVersions" : "NULL"
|
|
, is_versioned_functions ? "versionedFunctions" : "NULL");
|
|
|
|
/* Generate the storage for the external API pointers. */
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* The SIP API and the APIs of any imported modules. */\n"
|
|
"const sipAPIDef *sipAPI_%s;\n"
|
|
, mname);
|
|
|
|
for (mld = mod->allimports; mld != NULL; mld = mld->next)
|
|
prcode(fp,
|
|
"const sipExportedModuleDef *sipModuleAPI_%s_%s;\n"
|
|
, mname, mld->module->name);
|
|
|
|
if (pluginPyTQt4(pt))
|
|
prcode(fp,
|
|
"\n"
|
|
"sip_qt_metaobject_func sip_%s_qt_metaobject;\n"
|
|
"sip_qt_metacall_func sip_%s_qt_metacall;\n"
|
|
"sip_qt_metacast_func sip_%s_qt_metacast;\n"
|
|
, mname
|
|
, mname
|
|
, mname);
|
|
|
|
/* Generate the Python module initialisation function. */
|
|
|
|
if (mod->container == pt->module)
|
|
prcode(fp,
|
|
"\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
"#define SIP_MODULE_DISCARD(r) Py_DECREF(r)\n"
|
|
"#define SIP_MODULE_RETURN(r) return (r)\n"
|
|
"PyObject *sip_init_%s()\n"
|
|
"#else\n"
|
|
"#define SIP_MODULE_DISCARD(r)\n"
|
|
"#define SIP_MODULE_RETURN(r) return\n"
|
|
"void sip_init_%s()\n"
|
|
"#endif\n"
|
|
"{\n"
|
|
, mname
|
|
, mname);
|
|
else
|
|
generateModInitStart(pt->module, generating_c, fp);
|
|
|
|
/* Generate the global functions. */
|
|
|
|
prcode(fp,
|
|
" static PyMethodDef sip_methods[] = {\n"
|
|
);
|
|
|
|
for (md = mod->othfuncs; md != NULL; md = md->next)
|
|
if (md->slot == no_slot)
|
|
{
|
|
int has_docstring;
|
|
|
|
if (!notVersioned(md))
|
|
continue;
|
|
|
|
has_docstring = FALSE;
|
|
|
|
if (md->docstring != NULL || (docstrings && hasDocstring(pt, mod->overs, md, NULL)))
|
|
has_docstring = TRUE;
|
|
|
|
prcode(fp,
|
|
" {SIP_MLNAME_CAST(%N), ", md->pyname);
|
|
|
|
if (noArgParser(md) || useKeywordArgsFunction(md))
|
|
prcode(fp, "(PyCFunction)func_%s, METH_VARARGS|METH_KEYWORDS", md->pyname->text);
|
|
else
|
|
prcode(fp, "func_%s, METH_VARARGS", md->pyname->text);
|
|
|
|
if (has_docstring)
|
|
prcode(fp, ", SIP_MLDOC_CAST(doc_%s)},\n"
|
|
, md->pyname->text);
|
|
else
|
|
prcode(fp, ", NULL},\n"
|
|
);
|
|
}
|
|
|
|
prcode(fp,
|
|
" {0, 0, 0, 0}\n"
|
|
" };\n"
|
|
);
|
|
|
|
generateModDefinition(mod, "sip_methods", fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
" PyObject *sipModule, *sipModuleDict;\n"
|
|
);
|
|
|
|
generateSipImportVariables(fp);
|
|
|
|
/* Generate any pre-initialisation code. */
|
|
generateCppCodeBlock(mod->preinitcode, fp);
|
|
|
|
prcode(fp,
|
|
" /* Initialise the module and get it's dictionary. */\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" sipModule = PyModule_Create(&sip_module_def);\n"
|
|
"#elif PY_VERSION_HEX >= 0x02050000\n"
|
|
" sipModule = Py_InitModule(%N, sip_methods);\n"
|
|
"#else\n"
|
|
, mod->fullname);
|
|
|
|
if (generating_c)
|
|
prcode(fp,
|
|
" sipModule = Py_InitModule((char *)%N, sip_methods);\n"
|
|
, mod->fullname);
|
|
else
|
|
prcode(fp,
|
|
" sipModule = Py_InitModule(const_cast<char *>(%N), sip_methods);\n"
|
|
, mod->fullname);
|
|
|
|
prcode(fp,
|
|
"#endif\n"
|
|
"\n"
|
|
" if (sipModule == NULL)\n"
|
|
" SIP_MODULE_RETURN(NULL);\n"
|
|
"\n"
|
|
" sipModuleDict = PyModule_GetDict(sipModule);\n"
|
|
"\n"
|
|
);
|
|
|
|
generateSipImport(mod, fp);
|
|
|
|
/* Generate any initialisation code. */
|
|
generateCppCodeBlock(mod->initcode, fp);
|
|
|
|
prcode(fp,
|
|
" /* Export the module and publish it's API. */\n"
|
|
" if (sipExportModule(&sipModuleAPI_%s,SIP_API_MAJOR_NR,SIP_API_MINOR_NR,0) < 0)\n"
|
|
" {\n"
|
|
"#if !defined(SIP_USE_PYCAPSULE)\n"
|
|
" Py_DECREF(sip_sipmod);\n"
|
|
"#endif\n"
|
|
" SIP_MODULE_DISCARD(sipModule);\n"
|
|
" SIP_MODULE_RETURN(0);\n"
|
|
" }\n"
|
|
, mname);
|
|
|
|
if (pluginPyTQt4(pt))
|
|
{
|
|
/* Import the helpers. */
|
|
prcode(fp,
|
|
"\n"
|
|
" sip_%s_qt_metaobject = (sip_qt_metaobject_func)sipImportSymbol(\"qtcore_qt_metaobject\");\n"
|
|
" sip_%s_qt_metacall = (sip_qt_metacall_func)sipImportSymbol(\"qtcore_qt_metacall\");\n"
|
|
" sip_%s_qt_metacast = (sip_qt_metacast_func)sipImportSymbol(\"qtcore_qt_metacast\");\n"
|
|
"\n"
|
|
, mname
|
|
, mname
|
|
, mname);
|
|
}
|
|
|
|
prcode(fp,
|
|
" /* Initialise the module now all its dependencies have been set up. */\n"
|
|
" if (sipInitModule(&sipModuleAPI_%s,sipModuleDict) < 0)\n"
|
|
" {\n"
|
|
"#if !defined(SIP_USE_PYCAPSULE)\n"
|
|
" Py_DECREF(sip_sipmod);\n"
|
|
"#endif\n"
|
|
" SIP_MODULE_DISCARD(sipModule);\n"
|
|
" SIP_MODULE_RETURN(0);\n"
|
|
" }\n"
|
|
, mname);
|
|
|
|
mod_nr = 0;
|
|
|
|
for (mld = mod->allimports; mld != NULL; mld = mld->next)
|
|
{
|
|
if (mod_nr == 0)
|
|
prcode(fp,
|
|
"\n"
|
|
" /* Get the APIs of the modules that this one is dependent on. */\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
" sipModuleAPI_%s_%s = sipModuleAPI_%s.em_imports[%d].im_module;\n"
|
|
, mname, mld->module->name, mname, mod_nr);
|
|
|
|
++mod_nr;
|
|
}
|
|
|
|
generateTypesInline(pt, mod, fp);
|
|
|
|
/* Create any exceptions. */
|
|
for (xd = pt->exceptions; xd != NULL; xd = xd->next)
|
|
{
|
|
if (xd->iff->module != mod)
|
|
continue;
|
|
|
|
if (xd->iff->type != exception_iface)
|
|
continue;
|
|
|
|
if (xd->exceptionnr < 0)
|
|
continue;
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
" if ((exceptionsTable[%d] = PyErr_NewException(\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" \"%s.%s\",\n"
|
|
"#else\n"
|
|
" const_cast<char *>(\"%s.%s\"),\n"
|
|
"#endif\n"
|
|
" "
|
|
, xd->exceptionnr
|
|
, xd->iff->module->name, xd->pyname
|
|
, xd->iff->module->name, xd->pyname);
|
|
|
|
if (xd->bibase != NULL)
|
|
prcode(fp, "PyExc_%s", xd->bibase);
|
|
else if (xd->base->iff->module == mod)
|
|
prcode(fp, "exceptionsTable[%d]", xd->base->exceptionnr);
|
|
else
|
|
prcode(fp, "sipException_%C", xd->base->iff->fqcname);
|
|
|
|
prcode(fp, ",NULL)) == NULL || PyDict_SetItemString(sipModuleDict,\"%s\",exceptionsTable[%d]) < 0)\n"
|
|
" {\n"
|
|
"#if !defined(SIP_USE_PYCAPSULE)\n"
|
|
" Py_DECREF(sip_sipmod);\n"
|
|
"#endif\n"
|
|
" SIP_MODULE_DISCARD(sipModule);\n"
|
|
" SIP_MODULE_RETURN(0);\n"
|
|
" }\n"
|
|
, xd->pyname, xd->exceptionnr);
|
|
}
|
|
|
|
/* Generate any post-initialisation code. */
|
|
generateCppCodeBlock(mod->postinitcode, fp);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
" SIP_MODULE_RETURN(sipModule);\n"
|
|
"}\n"
|
|
);
|
|
|
|
/* Generate the interface source files. */
|
|
for (iff = pt->ifacefiles; iff != NULL; iff = iff->next)
|
|
if (iff->module == mod && iff->type != exception_iface)
|
|
{
|
|
if (parts && files_in_part++ == max_per_part)
|
|
{
|
|
/* Close the old part. */
|
|
closeFile(fp);
|
|
free(cppfile);
|
|
|
|
/* Create a new one. */
|
|
files_in_part = 1;
|
|
++this_part;
|
|
|
|
cppfile = makePartName(codeDir, mname, this_part, srcSuffix);
|
|
fp = createCompilationUnit(mod, cppfile, "Module code.");
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#include \"sipAPI%s.h\"\n"
|
|
, mname);
|
|
}
|
|
|
|
generateIfaceCpp(pt, iff, codeDir, srcSuffix, (parts ? fp : NULL));
|
|
}
|
|
|
|
closeFile(fp);
|
|
free(cppfile);
|
|
|
|
/* How many parts we actually generated. */
|
|
if (parts)
|
|
parts = this_part + 1;
|
|
|
|
mod->parts = parts;
|
|
|
|
generateInternalAPIHeader(pt, mod, codeDir, xsl);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the types table for a module.
|
|
*/
|
|
static void generateTypesTable(sipSpec *pt, moduleDef *mod, FILE *fp)
|
|
{
|
|
int i;
|
|
argDef *ad;
|
|
const char *type_suffix;
|
|
|
|
type_suffix = (pluginPyTQt4(pt) || pluginPyTQt3(pt)) ? ".super" : "";
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/*\n"
|
|
" * This defines each type in this module.\n"
|
|
" */\n"
|
|
"static sipTypeDef *typesTable[] = {\n"
|
|
);
|
|
|
|
for (ad = mod->types, i = 0; i < mod->nrtypes; ++i, ++ad)
|
|
{
|
|
switch (ad->atype)
|
|
{
|
|
case class_type:
|
|
if (isExternal(ad->u.cd))
|
|
prcode(fp,
|
|
" 0,\n"
|
|
);
|
|
else
|
|
prcode(fp,
|
|
" &sipTypeDef_%s_%L%s.ctd_base,\n"
|
|
, mod->name, ad->u.cd->iff, type_suffix);
|
|
|
|
break;
|
|
|
|
case mapped_type:
|
|
prcode(fp,
|
|
" &sipTypeDef_%s_%L.mtd_base,\n"
|
|
, mod->name, ad->u.mtd->iff);
|
|
break;
|
|
|
|
case enum_type:
|
|
prcode(fp,
|
|
" &enumTypes[%d].etd_base,\n"
|
|
, ad->u.ed->enum_idx);
|
|
break;
|
|
}
|
|
}
|
|
|
|
prcode(fp,
|
|
"};\n"
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the code to import the sip module and get its API.
|
|
*/
|
|
static void generateSipImport(moduleDef *mod, FILE *fp)
|
|
{
|
|
prcode(fp,
|
|
" /* Get the SIP module's API. */\n"
|
|
"#if defined(SIP_USE_PYCAPSULE)\n"
|
|
"\n"
|
|
);
|
|
|
|
if (generating_c)
|
|
prcode(fp,
|
|
" sipAPI_%s = (const sipAPIDef *)PyCapsule_Import(\"sip._C_API\", 0);\n"
|
|
, mod->name);
|
|
else
|
|
prcode(fp,
|
|
" sipAPI_%s = reinterpret_cast<const sipAPIDef *>(PyCapsule_Import(\"sip._C_API\", 0));\n"
|
|
, mod->name);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
" if (sipAPI_%s == NULL)\n"
|
|
" {\n"
|
|
" SIP_MODULE_DISCARD(sipModule);\n"
|
|
" SIP_MODULE_RETURN(NULL);\n"
|
|
" }\n"
|
|
"\n"
|
|
"#else\n"
|
|
"\n"
|
|
"#if PY_VERSION_HEX >= 0x02050000\n"
|
|
" sip_sipmod = PyImport_ImportModule(\"sip\");\n"
|
|
"#else\n"
|
|
, mod->name);
|
|
|
|
if (generating_c)
|
|
prcode(fp,
|
|
" sip_sipmod = PyImport_ImportModule((char *)\"sip\");\n"
|
|
);
|
|
else
|
|
prcode(fp,
|
|
" sip_sipmod = PyImport_ImportModule(const_cast<char *>(\"sip\"));\n"
|
|
);
|
|
|
|
prcode(fp,
|
|
"#endif\n"
|
|
"\n"
|
|
" if (sip_sipmod == NULL)\n"
|
|
" {\n"
|
|
" SIP_MODULE_DISCARD(sipModule);\n"
|
|
" SIP_MODULE_RETURN(NULL);\n"
|
|
" }\n"
|
|
"\n"
|
|
" sip_capiobj = PyDict_GetItemString(PyModule_GetDict(sip_sipmod), \"_C_API\");\n"
|
|
"\n"
|
|
" if (sip_capiobj == NULL || !PyCObject_Check(sip_capiobj))\n"
|
|
" {\n"
|
|
" Py_DECREF(sip_sipmod);\n"
|
|
" SIP_MODULE_DISCARD(sipModule);\n"
|
|
" SIP_MODULE_RETURN(NULL);\n"
|
|
" }\n"
|
|
"\n"
|
|
);
|
|
|
|
if (generating_c)
|
|
prcode(fp,
|
|
" sipAPI_%s = (const sipAPIDef *)PyCObject_AsVoidPtr(sip_capiobj);\n"
|
|
, mod->name);
|
|
else
|
|
prcode(fp,
|
|
" sipAPI_%s = reinterpret_cast<const sipAPIDef *>(PyCObject_AsVoidPtr(sip_capiobj));\n"
|
|
, mod->name);
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"#endif\n"
|
|
"\n"
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the variables needed by generateSipImport().
|
|
*/
|
|
static void generateSipImportVariables(FILE *fp)
|
|
{
|
|
prcode(fp,
|
|
"#if !defined(SIP_USE_PYCAPSULE)\n"
|
|
" PyObject *sip_sipmod, *sip_capiobj;\n"
|
|
"#endif\n"
|
|
"\n"
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the start of the Python module initialisation function.
|
|
*/
|
|
static void generateModInitStart(moduleDef *mod, int gen_c, FILE *fp)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* The Python module initialisation function. */\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
"#define SIP_MODULE_ENTRY PyInit_%s\n"
|
|
"#define SIP_MODULE_TYPE PyObject *\n"
|
|
"#define SIP_MODULE_DISCARD(r) Py_DECREF(r)\n"
|
|
"#define SIP_MODULE_RETURN(r) return (r)\n"
|
|
"#else\n"
|
|
"#define SIP_MODULE_ENTRY init%s\n"
|
|
"#define SIP_MODULE_TYPE void\n"
|
|
"#define SIP_MODULE_DISCARD(r)\n"
|
|
"#define SIP_MODULE_RETURN(r) return\n"
|
|
"#endif\n"
|
|
"\n"
|
|
"#if defined(SIP_STATIC_MODULE)\n"
|
|
"%sSIP_MODULE_TYPE SIP_MODULE_ENTRY()\n"
|
|
"#else\n"
|
|
"PyMODINIT_FUNC SIP_MODULE_ENTRY()\n"
|
|
"#endif\n"
|
|
"{\n"
|
|
, mod->name
|
|
, mod->name
|
|
, (gen_c ? "" : "extern \"C\" "));
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the Python v3 module definition structure.
|
|
*/
|
|
static void generateModDefinition(moduleDef *mod, const char *methods,
|
|
FILE *fp)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
"#if PY_MAJOR_VERSION >= 3\n"
|
|
" static PyModuleDef sip_module_def = {\n"
|
|
" PyModuleDef_HEAD_INIT,\n"
|
|
" \"%s\",\n"
|
|
" NULL,\n"
|
|
" -1,\n"
|
|
" %s,\n"
|
|
" NULL,\n"
|
|
" NULL,\n"
|
|
" NULL,\n"
|
|
" NULL\n"
|
|
" };\n"
|
|
"#endif\n"
|
|
, mod->fullname->text
|
|
, methods);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate all the sub-class convertors for a module.
|
|
*/
|
|
static int generateSubClassConvertors(sipSpec *pt, moduleDef *mod, FILE *fp)
|
|
{
|
|
int nrSccs = 0;
|
|
classDef *cd;
|
|
|
|
for (cd = pt->classes; cd != NULL; cd = cd->next)
|
|
{
|
|
int needs_sipClass;
|
|
|
|
if (cd->iff->module != mod)
|
|
continue;
|
|
|
|
if (cd->convtosubcode == NULL)
|
|
continue;
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
"/* Convert to a sub-class if possible. */\n"
|
|
);
|
|
|
|
if (!generating_c)
|
|
prcode(fp,
|
|
"extern \"C\" {static const sipTypeDef *sipSubClass_%C(void **);}\n"
|
|
, classFTQCName(cd));
|
|
|
|
/* Allow the deprecated use of sipClass rather than sipType. */
|
|
needs_sipClass = usedInCode(cd->convtosubcode, "sipClass");
|
|
|
|
prcode(fp,
|
|
"static const sipTypeDef *sipSubClass_%C(void **sipCppRet)\n"
|
|
"{\n"
|
|
" %S *sipCpp = reinterpret_cast<%S *>(*sipCppRet);\n"
|
|
, classFTQCName(cd)
|
|
, classFTQCName(cd->subbase), classFTQCName(cd->subbase));
|
|
|
|
if (needs_sipClass)
|
|
prcode(fp,
|
|
" sipWrapperType *sipClass;\n"
|
|
"\n"
|
|
);
|
|
else
|
|
prcode(fp,
|
|
" const sipTypeDef *sipType;\n"
|
|
"\n"
|
|
);
|
|
|
|
generateCppCodeBlock(cd->convtosubcode, fp);
|
|
|
|
if (needs_sipClass)
|
|
prcode(fp,
|
|
"\n"
|
|
" return (sipClass ? sipClass->type : 0);\n"
|
|
"}\n"
|
|
);
|
|
else
|
|
prcode(fp,
|
|
"\n"
|
|
" return sipType;\n"
|
|
"}\n"
|
|
);
|
|
|
|
++nrSccs;
|
|
}
|
|
|
|
return nrSccs;
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the structure representing an encoded type.
|
|
*/
|
|
static void generateEncodedType(moduleDef *mod, classDef *cd, int last,
|
|
FILE *fp)
|
|
{
|
|
moduleDef *cmod = cd->iff->module;
|
|
|
|
prcode(fp, "{%u, ", cd->iff->first_alt->ifacenr);
|
|
|
|
if (cmod == mod)
|
|
prcode(fp, "255");
|
|
else
|
|
{
|
|
int mod_nr = 0;
|
|
moduleListDef *mld;
|
|
|
|
for (mld = mod->allimports; mld != NULL; mld = mld->next)
|
|
{
|
|
if (mld->module == cmod)
|
|
{
|
|
prcode(fp, "%u", mod_nr);
|
|
break;
|
|
}
|
|
|
|
++mod_nr;
|
|
}
|
|
}
|
|
|
|
prcode(fp, ", %u}", last);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate an ordinary function.
|
|
*/
|
|
static void generateOrdinaryFunction(sipSpec *pt, moduleDef *mod,
|
|
classDef *c_scope, mappedTypeDef *mt_scope, memberDef *md, FILE *fp)
|
|
{
|
|
overDef *od;
|
|
int need_intro, has_auto_docstring;
|
|
ifaceFileDef *scope;
|
|
classDef *scope_scope;
|
|
const char *scope_name, *kw_fw_decl, *kw_decl;
|
|
|
|
if (mt_scope != NULL)
|
|
{
|
|
scope = mt_scope->iff;
|
|
scope_name = mt_scope->pyname->text;
|
|
scope_scope = NULL;
|
|
od = mt_scope->overs;
|
|
}
|
|
else if (c_scope != NULL)
|
|
{
|
|
scope = c_scope->iff;
|
|
scope_name = c_scope->pyname->text;
|
|
scope_scope = NULL;
|
|
od = c_scope->overs;
|
|
}
|
|
else
|
|
{
|
|
scope = NULL;
|
|
scope_name = NULL;
|
|
scope_scope = NULL;
|
|
od = mod->overs;
|
|
}
|
|
|
|
prcode(fp,
|
|
"\n"
|
|
"\n"
|
|
);
|
|
|
|
/* Generate the docstrings. */
|
|
has_auto_docstring = FALSE;
|
|
|
|
if (md->docstring != NULL || (docstrings && hasDocstring(pt, od, md, scope)))
|
|
{
|
|
if (scope != NULL)
|
|
prcode(fp,
|
|
"PyDoc_STRVAR(doc_%L_%s, ", scope, md->pyname->text);
|
|
else
|
|
prcode(fp,
|
|
"PyDoc_STRVAR(doc_%s, " , md->pyname->text);
|
|
|
|
if (md->docstring != NULL)
|
|
{
|
|
generateExplicitDocstring(md->docstring, fp);
|
|
}
|
|
else
|
|
{
|
|
generateDocstring(pt, od, md, scope_name, scope_scope, fp);
|
|
has_auto_docstring = TRUE;
|
|
}
|
|
|
|
prcode(fp, ");\n"
|
|
"\n"
|
|
);
|
|
}
|
|
|
|
if (noArgParser(md) || useKeywordArgsFunction(md))
|
|
{
|
|
kw_fw_decl = ", PyObject *";
|
|
kw_decl = ", PyObject *sipKwds";
|
|
}
|
|
else
|
|
{
|
|
kw_fw_decl = "";
|
|
kw_decl = "";
|
|
}
|
|
|
|
if (scope != NULL)
|
|
{
|
|
if (!generating_c)
|
|
prcode(fp,
|
|
"extern \"C\" {static PyObject *meth_%L_%s(PyObject *, PyObject *%s);}\n"
|
|
, scope, md->pyname->text, kw_fw_decl);
|
|
|
|
prcode(fp,
|
|
"static PyObject *meth_%L_%s(PyObject *, PyObject *sipArgs%s)\n"
|
|
, scope, md->pyname->text, kw_decl);
|
|
}
|
|
else
|
|
{
|
|
const char *self = (generating_c ? "sipSelf" : "");
|
|
|
|
if (!generating_c)
|
|
prcode(fp,
|
|
"extern \"C\" {static PyObject *func_%s(PyObject *,PyObject *%s);}\n"
|
|
, md->pyname->text, kw_fw_decl);
|
|
|
|
prcode(fp,
|
|
"static PyObject *func_%s(PyObject *%s,PyObject *sipArgs%s)\n"
|
|
, md->pyname->text, self, kw_decl);
|
|
}
|
|
|
|
prcode(fp,
|
|
"{\n"
|
|
);
|
|
|
|
need_intro = TRUE;
|
|
|
|
while (od != NULL)
|
|
{
|
|
if (od->common == md)
|
|
{
|
|
if (noArgParser(md))
|
|
{
|
|
generateCppCodeBlock(od->methodcode, fp);
|
|
break;
|
|
}
|
|
|
|
if (need_intro)
|
|
{
|
|
prcode(fp,
|
|
" PyObject *sipParseErr = NULL;\n"
|
|
);
|
|
|
|
need_intro = FALSE;
|
|
}
|
|
|
|
generateFunctionBody(od, c_scope, mt_scope, c_scope, TRUE, mod, fp);
|
|
}
|
|
|
|
od = od->next;
|
|
}
|
|
|
|
if (!need_intro)
|
|
{
|
|
prcode(fp,
|
|
"\n"
|
|
" /* Raise an exception if the arguments couldn't be parsed. */\n"
|
|
" sipNoFunction(sipParseErr, %N, ", md->pyname);
|
|
|
|
if (has_auto_docstring)
|
|
{
|
|
if (scope != NULL)
|
|
prcode(fp, "doc_%L_%s", scope, md->pyname->text);
|
|
else
|
|
prcode(fp, "doc_%s", md->pyname->text);
|
|
}
|
|
else
|
|
{
|
|
prcode(fp, "NULL");
|
|
}
|
|
|
|
prcode(fp, ");\n"
|
|
"\n"
|
|
" return NULL;\n"
|
|
);
|
|
}
|
|
|
|
prcode(fp,
|
|
"}\n"
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
* Generate the table of enum members for a scope. Return the number of them.
|
|
*/
|
|
static int generateEnumMemberTable(sipSpec *pt, moduleDef *mod, classDef *cd,
|
|
mappedTypeDef *mtd, FILE *fp)
|
|
{
|
|
int i, nr_members;
|
|
enumDef *ed;
|
|
enumMemberDef **etab, **et;
|
|
|
|
/* First we count how many. */
|
|
|
|
nr_members = 0;
|
|
|
|
for (ed = pt->enums; ed != NULL; ed = ed->next)
|
|
{
|
|
enumMemberDef *emd;
|
|
|
|
if (ed->module != mod)
|
|
continue;
|
|
|
|
if (cd != NULL)
|
|
{
|
|
if (ed->ecd != cd)
|
|
continue;
|
|
}
|
|
else if (mtd != NULL)
|
|
{
|
|
if (ed->emtd != mtd)
|
|
continue;
|
|
}
|
|
else if (ed->ecd != NULL || ed->emtd != NULL || ed->fqcname == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (emd = ed->members; emd != NULL; emd = emd->next)
|
|
++nr_members;
|
|
}
|
|
|
|
if (nr_members == 0)
|
|
return 0;
|
|
|
|
/* Create a table so they can be sorted. */
|
|
|
|
etab = sipCalloc(nr_members, sizeof (enumMemberDef *));
|
|
|
|
et = etab;
|
|
|
|
for (ed = pt->enums; ed != NULL; ed = ed->next)
|
|
{
|
|
en |