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.
sip4-tqt/sipgen/gencode.c

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