diff options
Diffstat (limited to 'python/sip/sipgen/gencode.c')
-rw-r--r-- | python/sip/sipgen/gencode.c | 10820 |
1 files changed, 0 insertions, 10820 deletions
diff --git a/python/sip/sipgen/gencode.c b/python/sip/sipgen/gencode.c deleted file mode 100644 index ff1b93b9..00000000 --- a/python/sip/sipgen/gencode.c +++ /dev/null @@ -1,10820 +0,0 @@ -/* - * The code generator module for SIP. - * - * Copyright (c) 2007 - * Riverbank Computing Limited <info@riverbankcomputing.co.uk> - * - * This file is part of SIP. - * - * This copy of SIP is licensed for use under the terms of the SIP License - * Agreement. See the file LICENSE for more details. - * - * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - - -#include <stdio.h> -#include <time.h> -#include <errno.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> - -#include "sip.h" - - -/* - * These must match the values of SIP_TYPE_FLAGS_SHIFT and SIP_TYPE_FLAGS_MASK - * in siplib/sip.h. - */ -#define TYPE_FLAGS_SHIFT 8 -#define TYPE_FLAGS_MASK 0x0f00 - - -/* Control what generateSingleArg() actually generates. */ -typedef enum { - Call, - Declaration, - Definition -} funcArgType; - - -/* An entry in the sorted array of methods. */ -typedef struct { - memberDef *md; /* The method. */ - int is_static; /* Set if all overloads are static. */ -} sortedMethTab; - - -static int currentLineNr; /* Current output line number. */ -static char *currentFileName; /* Current output file name. */ -static int previousLineNr; /* Previous output line number. */ -static 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 void generateDocumentation(sipSpec *, char *); -static void generateBuildFile(sipSpec *, char *, char *, int); -static void generateInternalAPIHeader(sipSpec *, char *, stringList *); -static void generateCpp(sipSpec *, char *, char *, int *); -static void generateIfaceCpp(sipSpec *, ifaceFileDef *, char *, char *, - FILE *); -static void generateMappedTypeCpp(mappedTypeDef *, FILE *); -static void generateImportedMappedTypeHeader(mappedTypeDef *mtd, sipSpec *pt, - FILE *fp); -static void generateMappedTypeHeader(mappedTypeDef *, int, FILE *); -static void generateClassCpp(classDef *cd, sipSpec *pt, FILE *fp); -static void generateImportedClassHeader(classDef *cd, sipSpec *pt, FILE *fp); -static void generateClassTableEntries(sipSpec *pt, nodeDef *nd, FILE *fp); -static void generateClassHeader(classDef *, int, sipSpec *, FILE *); -static void generateClassFunctions(sipSpec *, classDef *, FILE *); -static void generateShadowCode(sipSpec *, classDef *, FILE *); -static void generateFunction(sipSpec *, memberDef *, overDef *, classDef *, - classDef *, FILE *); -static void generateFunctionBody(sipSpec *, overDef *, classDef *, classDef *, - int deref, FILE *); -static void generateTypeDefinition(sipSpec *pt, classDef *cd, FILE *fp); -static void generateTypeInit(sipSpec *, classDef *, FILE *); -static void generateCppCodeBlock(codeBlock *, FILE *); -static void generateUsedIncludes(ifaceFileList *, int, FILE *); -static void generateIfaceHeader(sipSpec *, ifaceFileDef *, char *); -static void generateShadowClassDeclaration(sipSpec *, classDef *, FILE *); -static int hasConvertToCode(argDef *ad); -static void deleteTemps(signatureDef *sd, FILE *fp); -static void gc_ellipsis(signatureDef *sd, FILE *fp); -static void generateArgs(signatureDef *, funcArgType, FILE *); -static void generateVariable(argDef *, int, FILE *); -static void generateNamedValueType(argDef *, char *, FILE *); -static void generateSingleArg(argDef *, int, funcArgType, FILE *); -static void generateBaseType(argDef *, FILE *); -static void generateNamedBaseType(argDef *, char *, FILE *); -static void generateTupleBuilder(signatureDef *, FILE *); -static void generateEmitters(sipSpec *pt, classDef *cd, FILE *fp); -static void generateEmitter(sipSpec *, classDef *, visibleList *, FILE *); -static void generateVirtualHandler(sipSpec *, virtHandlerDef *, FILE *); -static void generateVirtHandlerErrorReturn(argDef *res, FILE *fp); -static void generateVirtualCatcher(sipSpec *, classDef *, int, virtOverDef *, - FILE *); -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(overDef *od, FILE *fp); -static void generateConstructorCall(classDef *, ctorDef *, int, FILE *); -static void generateHandleResult(overDef *, int, char *, FILE *); -static void generateOrdinaryFunction(sipSpec *, classDef *, memberDef *, - FILE *); -static void generateSimpleFunctionCall(fcallDef *, FILE *); -static void generateFunctionCall(classDef *cd, classDef *ocd, overDef *od, - int deref, FILE *fp); -static void generateCppFunctionCall(classDef *cd, classDef *ocd, overDef *od, - FILE *fp); -static void generateSlotArg(signatureDef *sd, int argnr, FILE *fp); -static void generateBinarySlotCall(overDef *od, char *op, int deref, FILE *fp); -static void generateNumberSlotCall(overDef *od, char *op, FILE *fp); -static void generateVariableHandler(varDef *, FILE *); -static int generateObjToCppConversion(argDef *, FILE *); -static void generateVarClassConversion(varDef *, FILE *); -static void generateVarMember(varDef *vd, FILE *fp); -static int generateVoidPointers(sipSpec *, classDef *, FILE *); -static int generateChars(sipSpec *, classDef *, FILE *); -static int generateStrings(sipSpec *, classDef *, FILE *); -static sortedMethTab *createFunctionTable(classDef *, int *); -static sortedMethTab *createMethodTable(classDef *, int *); -static int generateMethodTable(classDef *, FILE *); -static void generateEnumMacros(sipSpec *pt, classDef *cd, FILE *fp); -static int generateEnumMemberTable(sipSpec *, classDef *, FILE *); -static int generateInts(sipSpec *, classDef *, FILE *); -static int generateLongs(sipSpec *, classDef *, FILE *); -static int generateUnsignedLongs(sipSpec *, classDef *, FILE *); -static int generateLongLongs(sipSpec *, classDef *, FILE *); -static int generateUnsignedLongLongs(sipSpec *, classDef *, FILE *); -static int generateVariableType(sipSpec *pt, classDef *cd, argType atype, - const char *eng, const char *s1, const char *s2, FILE *fp); -static int generateDoubles(sipSpec *, classDef *, FILE *); -static int generateEnums(sipSpec *, classDef *, FILE *); -static int generateClasses(sipSpec *, classDef *, FILE *); -static void generateEnumsInline(sipSpec *, FILE *); -static void generateClassesInline(sipSpec *, FILE *); -static void generateAccessFunctions(sipSpec *, classDef *, FILE *); -static void generateConvertToDefinitions(mappedTypeDef *, classDef *, FILE *); -static void generateEncodedClass(sipSpec *, classDef *, int, FILE *); -static int generateArgParser(sipSpec *, signatureDef *, classDef *, ctorDef *, - overDef *, int, FILE *); -static void generateTry(throwArgs *, FILE *); -static void generateCatch(throwArgs *ta, signatureDef *sd, FILE *fp); -static void generateThrowSpecifier(throwArgs *, FILE *); -static void generateSlot(sipSpec *pt, 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(char *, ifaceFileDef *, char *); -static FILE *createCompilationUnit(sipSpec *pt, char *fname, - char *description); -static FILE *createFile(sipSpec *, char *, char *); -static void closeFile(FILE *); -static void prScopedName(FILE *fp, scopedNameDef *snd, char *sep); -static void prTypeName(FILE *, argDef *, int); -static void prScopedClassName(FILE *, classDef *, char *); -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 needNewInstance(argDef *ad); -static int needDealloc(classDef *cd); -static char getBuildResultFormat(argDef *ad); -static const char *getParseResultFormat(argDef *ad, int isres, int xfervh); -static void generateParseResultExtraArgs(argDef *ad, int isres, FILE *fp); -static char *makePartName(char *codeDir, char *mname, int part, - char *srcSuffix); -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, FILE *fp); -static void generateRegisterMetaType(classDef *cd, FILE *fp); - - -/* - * Generate the code from a specification. - */ -void generateCode(sipSpec *pt, char *codeDir, char *buildfile, char *docFile, - char *srcSuffix, int except, int trace, int releaseGIL, int parts, - stringList *xsl) -{ - exceptions = except; - tracing = trace; - release_gil = releaseGIL; - generating_c = pt->genc; - - if (srcSuffix == NULL) - srcSuffix = (generating_c ? ".c" : ".cpp"); - - /* Generate the documentation. */ - if (docFile != NULL) - generateDocumentation(pt,docFile); - - /* Generate the code. */ - if (codeDir != NULL) - { - generateCpp(pt,codeDir,srcSuffix,&parts); - generateInternalAPIHeader(pt,codeDir,xsl); - } - - /* Generate the build file. */ - if (buildfile != NULL) - generateBuildFile(pt,buildfile,srcSuffix,parts); -} - - -/* - * Generate the documentation. - */ -static void generateDocumentation(sipSpec *pt, char *docFile) -{ - FILE *fp; - codeBlock *cb; - - fp = createFile(pt, 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, char *buildFile, char *srcSuffix, - int parts) -{ - char *mname = pt->module->name; - ifaceFileDef *iff; - FILE *fp; - - fp = createFile(pt, buildFile, NULL); - - prcode(fp, "target = %s\nsources = ", mname); - - if (parts) - { - int p; - - for (p = 0; p < parts; ++p) - { - if (p > 0) - prcode(fp, " "); - - prcode(fp, "sip%spart%d%s", mname, p, srcSuffix); - } - } - else - { - prcode(fp, "sip%scmodule%s", mname, srcSuffix); - - for (iff = pt->ifacefiles; iff != NULL; iff = iff->next) - { - if (iff->module != pt->module) - continue; - - if (iff->type == exception_iface) - continue; - - prcode(fp, " sip%s%F%s", mname, iff->fqcname, srcSuffix); - } - } - - prcode(fp, "\nheaders = sipAPI%s.h", mname); - - for (iff = pt->ifacefiles; iff != NULL; iff = iff->next) - { - char *imname; - - imname = (iff->module == pt->module ? mname : iff->module->name); - - prcode(fp, " sip%s%F.h", imname, iff->fqcname); - } - - prcode(fp, "\n"); - - closeFile(fp); -} - - -/* - * Generate an expression in C++. - */ -void generateExpression(valueDef *vd, 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: - prcode(fp,"\"%s\"",vd->u.vstr); - 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,char *codeDir,stringList *xsl) -{ - char *hfile, *mname = pt->module->name; - int noIntro; - FILE *fp; - nameDef *nd; - moduleDef *mod; - moduleListDef *mld; - - hfile = concat(codeDir,"/sipAPI",mname,".h",NULL); - fp = createFile(pt,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 (optRegisterTypes(pt)) - prcode(fp, -"\n" -"#include <QMetaType>\n" - ); - - /* Define the enabled features. */ - noIntro = TRUE; - - for (mod = pt->modules; mod != NULL; mod = mod->next) - { - qualDef *qd; - - for (qd = mod->qualifiers; qd != NULL; qd = qd->next) - if (qd->qtype == feature_qualifier && !excludedFeature(xsl,qd)) - { - if (noIntro) - { - prcode(fp, -"\n" -"\n" -"/* These are the features that are enabled. */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -"#define SIP_FEATURE_%s\n" - ,qd->name); - } - } - - generateCppCodeBlock(pt->exphdrcode,fp); - generateCppCodeBlock(pt->hdrcode,fp); - - /* Shortcuts that hide the messy detail of the APIs. */ - noIntro = TRUE; - - for (nd = pt->namecache; nd != NULL; nd = nd->next) - { - if (!isClassName(nd)) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -"\n" -"/*\n" -" * Convenient names to refer to the names of classes defined in this module.\n" -" * These are part of the public API.\n" -" */\n" -"\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -"#define sipName_%s %N\n" - ,nd->text,nd); - } - - prcode(fp, -"\n" -"\n" -"/* Convenient names to call the SIP API. */\n" -"#define sipConvertFromSliceObject(o,len,start,stop,step,slen) PySlice_GetIndicesEx((PySliceObject *)(o),(len),(start),(stop),(step),(slen))\n" -"#define sipIsSubClassInstance(o,wt) PyObject_TypeCheck((o),(PyTypeObject *)(wt))\n" -"\n" -"#define sipMapStringToClass sipAPI_%s->api_map_string_to_class\n" -"#define sipMapIntToClass sipAPI_%s->api_map_int_to_class\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 sipParsePair sipAPI_%s->api_parse_pair\n" -"#define sipCommonCtor sipAPI_%s->api_common_ctor\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 sipConvertToCpp sipAPI_%s->api_convert_to_cpp\n" -"#define sipConvertToVoidPtr sipAPI_%s->api_convert_to_void_ptr\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 sipBadSetType sipAPI_%s->api_bad_set_type\n" -"#define sipBadCatcherResult sipAPI_%s->api_bad_catcher_result\n" -"#define sipBadOperatorArg sipAPI_%s->api_bad_operator_arg\n" -"#define sipTrace sipAPI_%s->api_trace\n" -"#define sipTransfer sipAPI_%s->api_transfer\n" -"#define sipTransferBack sipAPI_%s->api_transfer_back\n" -"#define sipTransferTo sipAPI_%s->api_transfer_to\n" -"#define sipWrapper_Check sipAPI_%s->api_wrapper_check\n" -"#define sipGetWrapper sipAPI_%s->api_get_wrapper\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 sipEmitSignal sipAPI_%s->api_emit_signal\n" -"#define sipConnectRx sipAPI_%s->api_connect_rx\n" -"#define sipDisconnectRx sipAPI_%s->api_disconnect_rx\n" -"#define sipGetSender sipAPI_%s->api_get_sender\n" -"#define sipRaiseUnknownException sipAPI_%s->api_raise_unknown_exception\n" -"#define sipRaiseClassException sipAPI_%s->api_raise_class_exception\n" -"#define sipRaiseSubClassException sipAPI_%s->api_raise_sub_class_exception\n" -"#define sipBadLengthForSlice sipAPI_%s->api_bad_length_for_slice\n" -"#define sipClassName sipAPI_%s->api_class_name\n" -"#define sipAddClassInstance sipAPI_%s->api_add_class_instance\n" -"#define sipAddMappedTypeInstance sipAPI_%s->api_add_mapped_type_instance\n" -"#define sipAddEnumInstance sipAPI_%s->api_add_enum_instance\n" -"#define sipConvertFromNamedEnum sipAPI_%s->api_convert_from_named_enum\n" -"#define sipGetAddress sipAPI_%s->api_get_address\n" -"#define sipFreeConnection sipAPI_%s->api_free_connection\n" -"#define sipEmitToSlot sipAPI_%s->api_emit_to_slot\n" -"#define sipSameConnection sipAPI_%s->api_same_connection\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 sipCanConvertToInstance sipAPI_%s->api_can_convert_to_instance\n" -"#define sipCanConvertToMappedType sipAPI_%s->api_can_convert_to_mapped_type\n" -"#define sipConvertToInstance sipAPI_%s->api_convert_to_instance\n" -"#define sipConvertToMappedType sipAPI_%s->api_convert_to_mapped_type\n" -"#define sipForceConvertToInstance sipAPI_%s->api_force_convert_to_instance\n" -"#define sipForceConvertToMappedType sipAPI_%s->api_force_convert_to_mapped_type\n" -"#define sipReleaseInstance sipAPI_%s->api_release_instance\n" -"#define sipReleaseMappedType sipAPI_%s->api_release_mapped_type\n" -"#define sipConvertFromInstance sipAPI_%s->api_convert_from_instance\n" -"#define sipConvertFromNewInstance sipAPI_%s->api_convert_from_new_instance\n" -"#define sipConvertFromMappedType sipAPI_%s->api_convert_from_mapped_type\n" -"#define sipGetState sipAPI_%s->api_get_state\n" -"#define sipFindMappedType sipAPI_%s->api_find_mapped_type\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 sipRegisterIntTypes sipAPI_%s->api_register_int_types\n" -"#define sipParseSignature sipAPI_%s->api_parse_signature\n" -"#define sipFindClass sipAPI_%s->api_find_class\n" -"#define sipFindNamedEnum sipAPI_%s->api_find_named_enum\n" -"#define sipString_AsChar sipAPI_%s->api_string_as_char\n" -"#define sipUnicode_AsWChar sipAPI_%s->api_unicode_as_wchar\n" -"#define sipUnicode_AsWString sipAPI_%s->api_unicode_as_wstring\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); - - /* The name strings. */ - noIntro = TRUE; - - for (nd = pt->namecache; nd != NULL; nd = nd->next) - { - if (!isUsedName(nd)) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -"\n" -"/* The strings used by this module. */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -"extern char %N[];\n" - ,nd); - } - - /* The unscoped enum macros. */ - generateEnumMacros(pt, NULL, fp); - - prcode(fp, -"\n" -"\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 = pt->module->allimports; mld != NULL; mld = mld->next) - prcode(fp, -"extern const sipExportedModuleDef *sipModuleAPI_%s_%s;\n" - ,mname,mld->module->name); - - if (optQ_OBJECT4(pt)) - prcode(fp, -"\n" -"typedef const TQMetaObject *(*sip_qt_metaobject_func)(sipWrapper *,sipWrapperType *,const TQMetaObject *);\n" -"extern sip_qt_metaobject_func sip_%s_qt_metaobject;\n" -"\n" -"typedef int (*sip_qt_metacall_func)(sipWrapper *,sipWrapperType *,TQMetaObject::Call,int,void **);\n" -"extern sip_qt_metacall_func sip_%s_qt_metacall;\n" - , 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(char *codeDir,char *mname,int part,char *srcSuffix) -{ - char buf[20]; - - sprintf(buf,"part%d",part); - - return concat(codeDir,"/sip",mname,buf,srcSuffix,NULL); -} - - -/* - * Generate the C/C++ code. - */ -static void generateCpp(sipSpec *pt, char *codeDir, char *srcSuffix, int *parts) -{ - char *cppfile, *mname = pt->module->name; - int noIntro, nrSccs = 0, files_in_part, max_per_part, this_part; - 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, is_inst_enum, nr_enummembers; - int hasexternal = FALSE, slot_extenders = FALSE, ctor_extenders = FALSE; - FILE *fp; - moduleListDef *mld; - classDef *cd; - memberDef *md; - ifaceFileDef *iff; - virtHandlerDef *vhd; - nameDef *nd; - 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 == pt->module) - ++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(pt, cppfile, "Module code."); - - prcode(fp, -"\n" -"#include \"sipAPI%s.h\"\n" -"\n" - ,mname); - - for (iff = pt->ifacefiles; iff != NULL; iff = iff->next) - if (iff->module == pt->module && iff->type != exception_iface) - prcode(fp, -"#include \"sip%s%F.h\"\n" - ,iff->module->name,iff->fqcname); - - generateUsedIncludes(pt->used, FALSE, fp); - - /* - * If there should be a Qt support API then generate stubs values for the - * optional parts. These should be undefined in %ModuleCode if a C++ - * implementation is provided. - */ - if (pt->qobjclass >= 0) - prcode(fp, -"\n" -"#define sipQtIsQtSignal 0\n" -"#define sipQtCreateUniversalSignalShortcut 0\n" -"#define sipQtCreateUniversalSignal 0\n" -"#define sipQtFindUniversalSignalShortcut 0\n" -"#define sipQtFindUniversalSignal 0\n" -"#define sipQtEmitSignalShortcut 0\n" -"#define sipQtEmitSignal 0\n" - ); - - /* Define the names. */ - noIntro = TRUE; - - for (nd = pt->namecache; nd != NULL; nd = nd->next) - { - if (!isUsedName(nd)) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -"\n" -"/* Define the strings used by this module. */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -"char %N[] = \"%s\";\n" - ,nd,nd->text); - } - - /* Generate the C++ code blocks. */ - generateCppCodeBlock(pt->cppcode,fp); - - /* Generate any virtual handler declarations. */ - for (vhd = pt->module->virthandlers; vhd != NULL; vhd = vhd->next) - if (!isDuplicateVH(vhd)) - generateVirtualHandler(pt,vhd,fp); - - /* Generate the global functions. */ - for (md = pt->othfuncs; md != NULL; md = md->next) - { - if (md->module != pt->module) - continue; - - if (md->slot == no_slot) - generateOrdinaryFunction(pt,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 = pt->overs; od != NULL; od = od->next) - if (od->common == md) - { - generateSlot(pt, NULL, NULL, md, fp); - slot_extenders = TRUE; - break; - } - } - } - - /* Generate any class specific ctor or slot extenders. */ - for (cd = pt->proxies; cd != NULL; cd = cd->next) - { - if (cd->ctors != NULL) - { - generateTypeInit(pt, cd, fp); - ctor_extenders = TRUE; - } - - for (md = cd->members; md != NULL; md = md->next) - { - generateSlot(pt, cd, NULL, md, fp); - slot_extenders = TRUE; - } - } - - /* Generate any ctor extender table. */ - if (ctor_extenders) - { - prcode(fp, -"\n" -"static sipInitExtenderDef initExtenders[] = {\n" - ); - - for (cd = pt->proxies; cd != NULL; cd = cd->next) - if (cd->ctors != NULL) - { - prcode(fp, -" {init_%C, ", classFQCName(cd)); - - generateEncodedClass(pt, cd, 0, fp); - - prcode(fp, ", NULL},\n" - ); - } - - prcode(fp, -" {NULL, {0, 0, 0}, NULL}\n" -"};\n" - ); - } - - /* Generate any slot extender table. */ - if (slot_extenders) - { - prcode(fp, -"\n" -"static sipPySlotExtenderDef slotExtenders[] = {\n" - ); - - for (md = pt->othfuncs; md != NULL; md = md->next) - { - overDef *od; - - if (md->module != pt->module) - continue; - - if (md->slot == no_slot) - continue; - - for (od = pt->overs; od != NULL; od = od->next) - if (od->common == md) - { - prcode(fp, -" {(void *)slot_%s, %s, {0, 0, 0}},\n" - , md->pyname->text, slotName(md->slot)); - - break; - } - } - - for (cd = pt->proxies; cd != NULL; cd = cd->next) - for (md = cd->members; md != NULL; md = md->next) - { - prcode(fp, -" {(void *)slot_%C_%s, %s, ", classFQCName(cd), md->pyname->text, slotName(md->slot)); - - generateEncodedClass(pt, cd, 0, fp); - - prcode(fp, "},\n" - ); - } - - prcode(fp, -" {NULL, (sipPySlotType)0, {0, 0, 0}}\n" -"};\n" - ); - } - - /* Generate the global access functions. */ - generateAccessFunctions(pt,NULL,fp); - - /* Generate the module data structures. */ - if (pt->module->nrclasses > 0) - { - nrSccs = generateSubClassConvertors(pt, fp); - - prcode(fp, -"\n" -"\n" -"/*\n" -" * This defines each class in this module. The values are replaced by the\n" -" * proper Python types during the export process.\n" -" */\n" -"static sipWrapperType *typesTable[] = {\n" - ); - - generateClassTableEntries(pt, &pt->module->root, fp); - - prcode(fp, -"};\n" - ); - - /* Generate the external classes table if needed. */ - for (cd = pt->classes; cd != NULL; cd = cd->next) - { - if (!isExternal(cd)) - continue; - - if (cd->iff->module != pt->module) - 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->classnr); - prScopedName(fp, classFQCName(cd), "."); - prcode(fp,"\"},\n" - ); - } - - if (hasexternal) - prcode(fp, -" {-1, NULL}\n" -"};\n" - ); - } - - if (pt->module->nrmappedtypes > 0) - { - mappedTypeDef *mtd; - argDef type; - - type.argflags = 0; - type.name = NULL; - type.nrderefs = 0; - type.defval = NULL; - - prcode(fp, -"\n" -"\n" -"/* This defines each mapped type in this module. */\n" -"static sipMappedType *mappedTypesTable[] = {\n" - ); - - for (mtd = pt->mappedtypes; mtd != NULL; mtd = mtd->next) - { - if (mtd->iff->module != pt->module) - continue; - - type.atype = mapped_type; - type.u.mtd = mtd; - - prcode(fp, -" &sipMappedTypeDef_%T,\n" - ,&type); - } - - prcode(fp, -" 0\n" -"};\n" - ); - } - - if (pt->module->nrenums > 0) - { - enumDef *ed; - - prcode(fp, -"\n" -"\n" -"/* Define each named enum in this module. */\n" - ); - - /* Generate any slot tables. */ - for (ed = pt->enums; ed != NULL; ed = ed->next) - { - memberDef *slot; - - if (ed->module != pt->module || ed->fqcname == NULL) - continue; - - if (ed->slots == NULL) - continue; - - for (slot = ed->slots; slot != NULL; slot = slot->next) - generateSlot(pt, 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) - prcode(fp, -" {(void *)slot_%C_%s, %s},\n" - , ed->fqcname, slot->pyname->text, stype); - } - - prcode(fp, -" {0, (sipPySlotType)0}\n" -"};\n" -"\n" - ); - } - - prcode(fp, -"static sipEnumDef enumTypesTable[] = {\n" - ); - - for (ed = pt->enums; ed != NULL; ed = ed->next) - { - char *emname; - - if (ed->module != pt->module || ed->fqcname == NULL) - continue; - - if (ed->ecd == NULL) - emname = mname; - else if (ed->ecd->real == NULL) - emname = ed->module->name; - else - emname = ed->ecd->real->iff->module->name; - - prcode(fp, -" {\"%s.%P\", ", emname, ed->ecd, ed->pyname->text); - - if (isRenamedEnum(ed) || (ed->ecd != NULL && isRenamedClass(ed->ecd))) - prcode(fp, "\"%S\", ", ed->fqcname); - else - prcode(fp, "NULL, "); - - if (ed->ecd == NULL) - prcode(fp, "-1"); - else - prcode(fp, "%d", ed->ecd->classnr); - - if (ed->slots != NULL) - prcode(fp, ", slots_%C", ed->fqcname); - else - prcode(fp, ", NULL"); - - prcode(fp, "},\n" - ); - } - - prcode(fp, -"};\n" - ); - - nr_enummembers = generateEnumMemberTable(pt,NULL,fp); - } - else - nr_enummembers = 0; - - if (pt->module->nrtypedefs > 0) - { - typedefDef *td; - - prcode(fp, -"\n" -"\n" -"/*\n" -" * These define each typedef in this module. They are only needed in case\n" -" * they are used as arguments to Qt signals.\n" -" */\n" -"\n" -"static sipTypedefDef typedefsTable[] = {\n" - ); - - for (td = pt->typedefs; td != NULL; td = td->next) - { - char *tdmname, *sat; - scopedNameDef *fqname; - - if (td->module != pt->module) - continue; - - fqname = NULL; - tdmname = NULL; - sat = "unknown"; - - switch (td->type.atype) - { - case string_type: - sat = (td->type.nrderefs == 0 ? "char" : "string"); - break; - - case sstring_type: - sat = (td->type.nrderefs == 0 ? "schar" : "sstring"); - break; - - case ustring_type: - sat = (td->type.nrderefs == 0 ? "uchar" : "ustring"); - break; - - case wstring_type: - sat = (td->type.nrderefs == 0 ? "wchar" : "wstring"); - break; - - case short_type: - sat = "short"; - break; - - case ushort_type: - sat = "ushort"; - break; - - case cint_type: - case int_type: - sat = "int"; - break; - - case uint_type: - sat = "uint"; - break; - - case long_type: - sat = "long"; - break; - - case ulong_type: - sat = "ulong"; - break; - - case longlong_type: - sat = "longlong"; - break; - - case ulonglong_type: - sat = "ulonglong"; - break; - - case cfloat_type: - case float_type: - sat = "float"; - break; - - case cdouble_type: - case double_type: - sat = "double"; - break; - - case bool_type: - case cbool_type: - sat = "bool"; - break; - - case void_type: - if (td->type.nrderefs != 0) - sat = "void"; - break; - - case enum_type: - if ((fqname = td->type.u.ed->fqcname) != NULL) - { - sat = "enum"; - - if (td->type.u.ed->module != pt->module) - tdmname = td->type.u.ed->module->fullname; - } - break; - - case class_type: - sat = "class"; - fqname = classFQCName(td->type.u.cd); - - if (td->type.u.cd->iff->module != pt->module) - tdmname = td->type.u.cd->iff->module->fullname; - break; - - case mapped_type: - sat = "mtype"; - fqname = td->type.u.mtd->iff->fqcname; - - if (td->type.u.mtd->iff->module != pt->module) - tdmname = td->type.u.mtd->iff->module->fullname; - break; - } - - prcode(fp, -" {\"%S\", %s_sat", td->fqname, sat); - - if (fqname != NULL) - prcode(fp, ", \"%S\"", fqname); - else - prcode(fp, ", NULL"); - - if (tdmname != NULL) - prcode(fp, ", \"%s\"", tdmname); - else - prcode(fp, ", NULL"); - - prcode(fp, "},\n" - ); - } - - prcode(fp, -" {NULL, unknown_sat, NULL, NULL}\n" -"};\n" - ); - } - - if (pt->module->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 = pt->module->virthandlers; vhd != NULL; vhd = vhd->next) - if (!isDuplicateVH(vhd)) - prcode(fp, -" (sipVirtHandlerFunc)sipVH_%s_%d,\n" - ,mname,vhd->virthandlernr); - - prcode(fp, -"};\n" - ); - } - - if (pt->module->allimports != NULL) - { - prcode(fp, -"\n" -"\n" -"/* This defines the modules that this module needs to import. */\n" -"static sipImportedModuleDef importsTable[] = {\n" - ); - - for (mld = pt->module->allimports; mld != NULL; mld = mld->next) - prcode(fp, -" {\"%s\", %d, NULL},\n" - , mld->module->fullname, 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 != pt->module) - continue; - - if (cd->convtosubcode == NULL) - continue; - - prcode(fp, -" {sipSubClass_%C, ",classFQCName(cd)); - - generateEncodedClass(pt,cd->subbase,0,fp); - - prcode(fp,", NULL},\n"); - } - - prcode(fp, -" {NULL, {0, 0, 0}, NULL}\n" -"};\n" - ); - } - - /* Generate any license information. */ - if (pt->module->license != NULL) - { - licenseDef *ld = pt->module->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,NULL,fp); - is_inst_voidp = generateVoidPointers(pt,NULL,fp); - is_inst_char = generateChars(pt,NULL,fp); - is_inst_string = generateStrings(pt,NULL,fp); - is_inst_int = generateInts(pt,NULL,fp); - is_inst_long = generateLongs(pt,NULL,fp); - is_inst_ulong = generateUnsignedLongs(pt,NULL,fp); - is_inst_longlong = generateLongLongs(pt,NULL,fp); - is_inst_ulonglong = generateUnsignedLongLongs(pt,NULL,fp); - is_inst_double = generateDoubles(pt,NULL,fp); - is_inst_enum = generateEnums(pt,NULL,fp); - - /* Generate any exceptions table. */ - if (pt->module->nrexceptions > 0) - prcode(fp, -"\n" -"\n" -"static PyObject *exceptionsTable[%d];\n" - ,pt->module->nrexceptions); - - /* Generate any Qt support API. */ - if (pt->qobjclass >= 0) - prcode(fp, -"\n" -"\n" -"/* This defines the Qt support API. */\n" -"\n" -"static sipQtAPI qtAPI = {\n" -" &typesTable[%d],\n" -" sipQtIsQtSignal,\n" -" sipQtCreateUniversalSignalShortcut,\n" -" sipQtCreateUniversalSignal,\n" -" sipQtFindUniversalSignalShortcut,\n" -" sipQtFindUniversalSignal,\n" -" sipQtEmitSignalShortcut,\n" -" sipQtEmitSignal,\n" -" sipQtCreateUniversalSlot,\n" -" sipQtDestroyUniversalSlot,\n" -" sipQtFindSlot,\n" -" sipQtConnect,\n" -" sipQtDisconnect,\n" -" sipQtSignalsBlocked,\n" -" sipQtGetSender,\n" -" sipQtForgetSender,\n" -" sipQtSameSignalSlotName,\n" -" sipQtFindConnection\n" -"};\n" - ,pt->qobjclass); - - prcode(fp, -"\n" -"\n" -"/* This defines this module. */\n" -"sipExportedModuleDef sipModuleAPI_%s = {\n" -" NULL,\n" -" SIP_API_MINOR_NR,\n" -" \"%s\",\n" -" NULL,\n" -" %d,\n" -" %s,\n" -" %s,\n" -" %d,\n" -" %s,\n" -" %s,\n" -" %s,\n" -" %d,\n" -" NULL,\n" -" %s,\n" -" %d,\n" -" %s,\n" -" %s,\n" -" %s,\n" -" %s,\n" -" {%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s},\n" -" %s,\n" -" %s,\n" -" %s,\n" -" %s,\n" -" %s,\n" -" NULL\n" -"};\n" - , mname - , pt->module->fullname - , pt->module->version - , pt->module->allimports != NULL ? "importsTable" : "NULL" - , pt->qobjclass >= 0 ? "&qtAPI" : "NULL" - , pt->module->nrclasses - , pt->module->nrclasses > 0 ? "typesTable" : "NULL" - , hasexternal ? "externalTypesTable" : "NULL" - , pt->module->nrmappedtypes > 0 ? "mappedTypesTable" : "NULL" - , pt->module->nrenums - , pt->module->nrenums > 0 ? "enumTypesTable" : "NULL" - , nr_enummembers - , nr_enummembers > 0 ? "enummembers" : "NULL" - , pt->module->nrtypedefs > 0 ? "typedefsTable" : "NULL" - , pt->module->nrvirthandlers > 0 ? "virtHandlersTable" : "NULL" - , nrSccs > 0 ? "convertorsTable" : "NULL" - , is_inst_class ? "classInstances" : "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" - , is_inst_enum ? "enumInstances" : "NULL" - , pt->module->license != NULL ? "&module_license" : "NULL" - , pt->module->nrexceptions > 0 ? "exceptionsTable" : "NULL" - , slot_extenders ? "slotExtenders" : "NULL" - , ctor_extenders ? "initExtenders" : "NULL" - , hasDelayedDtors(pt->module) ? "sipDelayedDtors" : "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 = pt->module->allimports; mld != NULL; mld = mld->next) - prcode(fp, -"const sipExportedModuleDef *sipModuleAPI_%s_%s;\n" - ,mname,mld->module->name); - - if (optQ_OBJECT4(pt)) - prcode(fp, -"\n" -"sip_qt_metaobject_func sip_%s_qt_metaobject;\n" -"sip_qt_metacall_func sip_%s_qt_metacall;\n" - , mname - , mname); - - /* Generate the Python module initialisation function. */ - prcode(fp, -"\n" -"\n" -"/* The Python module initialisation function. */\n" -"#if defined(SIP_STATIC_MODULE)\n" -"%svoid init%s()\n" -"#else\n" -"PyMODINIT_FUNC init%s()\n" -"#endif\n" -"{\n" -" static PyMethodDef sip_methods[] = {\n" - ,(generating_c ? "" : "extern \"C\" "), mname - ,mname); - - /* Generate the global functions. */ - - for (md = pt->othfuncs; md != NULL; md = md->next) - if (md->module == pt->module && md->slot == no_slot) - prcode(fp, -" {%N, func_%s, METH_VARARGS, NULL},\n" - ,md->pyname,md->pyname->text); - - prcode(fp, -" {0, 0, 0, 0}\n" -" };\n" -"\n" -" PyObject *sipModule, *sipModuleDict, *sip_sipmod, *sip_capiobj;\n" -"\n" - ); - - /* Generate the pre-initialisation code. */ - generateCppCodeBlock(pt->preinitcode,fp); - - prcode(fp, -" /* Initialise the module and get it's dictionary. */\n" -" sipModule = Py_InitModule((char *)sipModuleAPI_%s.em_name,sip_methods);\n" -" sipModuleDict = PyModule_GetDict(sipModule);\n" -"\n" -" /* Import the SIP module and get it's API. */\n" -" sip_sipmod = PyImport_ImportModule((char *)\"sip\");\n" -"\n" -" if (sip_sipmod == NULL)\n" -" return;\n" -"\n" -" sip_capiobj = PyDict_GetItemString(PyModule_GetDict(sip_sipmod),\"_C_API\");\n" -"\n" -" if (sip_capiobj == NULL || !PyCObject_Check(sip_capiobj))\n" -" return;\n" -"\n" - ,mname); - - if (generating_c) - prcode(fp, -" sipAPI_%s = (const sipAPIDef *)PyCObject_AsVoidPtr(sip_capiobj);\n" - ,mname); - else - prcode(fp, -" sipAPI_%s = reinterpret_cast<const sipAPIDef *>(PyCObject_AsVoidPtr(sip_capiobj));\n" - ,mname); - - prcode(fp, -"\n" -" /* Export the module and publish it's API. */\n" -" if (sipAPI_%s->api_export_module(&sipModuleAPI_%s,SIP_API_MAJOR_NR,SIP_API_MINOR_NR,sipModuleDict) < 0)\n" -" return;\n" - ,mname - ,mname); - - noIntro = TRUE; - - for (mld = pt->module->allimports; mld != NULL; mld = mld->next) - { - if (noIntro) - { - prcode(fp, -"\n" -" /* Get the APIs of the modules that this one is dependent on. */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" sipModuleAPI_%s_%s = sipModuleAPI_%s.em_imports[%d].im_module;\n" - ,mname,mld->module->name,mname,mld->module->modulenr); - } - - generateClassesInline(pt,fp); - generateEnumsInline(pt, fp); - - /* Create any exceptions. */ - for (xd = pt->exceptions; xd != NULL; xd = xd->next) - { - if (xd->iff->module != pt->module) - continue; - - if (xd->iff->type != exception_iface) - continue; - - if (xd->exceptionnr < 0) - continue; - - prcode(fp, -"\n" -" if ((exceptionsTable[%d] = PyErr_NewException((char *)\"%s.%s\",", xd->exceptionnr, xd->iff->module->name, xd->pyname); - - if (xd->bibase != NULL) - prcode(fp, "PyExc_%s", xd->bibase); - else if (xd->base->iff->module == pt->module) - 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" -" return;\n" - , xd->pyname, xd->exceptionnr); - } - - /* Generate any Qt metatype registration calls. */ - if (optRegisterTypes(pt)) - for (cd = pt->classes; cd != NULL; cd = cd->next) - { - if (cd->iff->module != pt->module) - continue; - - generateRegisterMetaType(cd, fp); - } - - /* Generate the post-initialisation code. */ - generateCppCodeBlock(pt->postinitcode,fp); - - /* - * This has to be done after the post-initialisation code in case this - * module is exporting the symbol. - */ - if (optQ_OBJECT4(pt)) - 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" - , mname - , mname); - - prcode(fp, -"}\n" - ); - - /* Generate the interface source and header files. */ - for (iff = pt->ifacefiles; iff != NULL; iff = iff->next) - { - if (iff->module == pt->module && 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(pt, cppfile, "Module code."); - } - - generateIfaceCpp(pt,iff,codeDir,srcSuffix,(*parts ? fp : NULL)); - } - - generateIfaceHeader(pt,iff,codeDir); - } - - closeFile(fp); - free(cppfile); - - /* How many parts we actually generated. */ - if (*parts) - *parts = this_part + 1; -} - - -/* - * Generate all the sub-class convertors for a module. - */ -static int generateSubClassConvertors(sipSpec *pt, FILE *fp) -{ - int nrSccs = 0; - classDef *cd; - - for (cd = pt->classes; cd != NULL; cd = cd->next) - { - if (cd->iff->module != pt->module) - 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 sipWrapperType *sipSubClass_%C(void **);}\n" - , classFQCName(cd)); - - prcode(fp, -"static sipWrapperType *sipSubClass_%C(void **sipCppRet)\n" -"{\n" -" %S *sipCpp = reinterpret_cast<%S *>(*sipCppRet);\n" -" sipWrapperType *sipClass;\n" -"\n" - , classFQCName(cd) - , classFQCName(cd->subbase), classFQCName(cd->subbase)); - - generateCppCodeBlock(cd->convtosubcode, fp); - - prcode(fp, -"\n" -" return sipClass;\n" -"}\n" - ); - - ++nrSccs; - } - - return nrSccs; -} - - -/* - * Generate an entry for a class in the classes table and all its children. - */ -static void generateClassTableEntries(sipSpec *pt, nodeDef *nd, FILE *fp) -{ - nodeDef *cnd; - - /* Generate the entry if it's not the root. */ - if (nd->cd != NULL) - if (isExternal(nd->cd)) - prcode(fp, -" 0,\n" - ); - else - prcode(fp, -" (sipWrapperType *)(void *)&sipType_%s_%C,\n" - , pt->module->name, classFQCName(nd->cd)); - - /* Generate all it's children. */ - for (cnd = nd->child; cnd != NULL; cnd = cnd->next) - generateClassTableEntries(pt, cnd, fp); -} - - -/* - * Generate the structure representing an encoded class. - */ -static void generateEncodedClass(sipSpec *pt,classDef *cd,int last,FILE *fp) -{ - moduleDef *mod = cd->iff->module; - - prcode(fp,"{%u, ",cd->classnr); - - if (mod == pt->module) - prcode(fp,"255"); - else - prcode(fp,"%u",mod->modulenr); - - prcode(fp,", %u}",last); -} - - -/* - * Generate an ordinary function (ie. not a class method). - */ -static void generateOrdinaryFunction(sipSpec *pt,classDef *cd,memberDef *md, - FILE *fp) -{ - overDef *od; - - prcode(fp, -"\n" -"\n" - ); - - if (cd != NULL) - { - if (!generating_c) - prcode(fp, -"extern \"C\" {static PyObject *meth_%C_%s(PyObject *,PyObject *);}\n" - , classFQCName(cd), md->pyname->text); - - prcode(fp, -"static PyObject *meth_%C_%s(PyObject *,PyObject *sipArgs)\n" - ,classFQCName(cd),md->pyname->text); - - od = cd->overs; - } - else - { - if (!generating_c) - prcode(fp, -"extern \"C\" {static PyObject *func_%s(PyObject *,PyObject *);}\n" - , md->pyname->text); - - prcode(fp, -"static PyObject *func_%s(PyObject *%s,PyObject *sipArgs)\n" - ,md->pyname->text,(generating_c ? "sipSelf" : "")); - - od = pt->overs; - } - - prcode(fp, -"{\n" -" int sipArgsParsed = 0;\n" - ); - - while (od != NULL) - { - if (od->common == md) - generateFunctionBody(pt,od,cd,cd,TRUE,fp); - - od = od->next; - } - - prcode(fp, -"\n" -" /* Raise an exception if the arguments couldn't be parsed. */\n" -" sipNoFunction(sipArgsParsed,%N);\n" -"\n" -" return NULL;\n" -"}\n" - ,md->pyname); -} - - -/* - * Generate the table of enum members for a scope. Return the number of them. - */ -static int generateEnumMemberTable(sipSpec *pt,classDef *cd,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->ecd != cd || ed->module != pt->module) - continue; - - if (cd == 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 = sipMalloc(sizeof (enumMemberDef *) * nr_members); - - et = etab; - - for (ed = pt->enums; ed != NULL; ed = ed->next) - { - enumMemberDef *emd; - - if (ed->ecd != cd || ed->module != pt->module) - continue; - - if (cd == NULL && ed->fqcname == NULL) - continue; - - for (emd = ed->members; emd != NULL; emd = emd->next) - *et++ = emd; - } - - qsort(etab,nr_members,sizeof (enumMemberDef *),compareEnumMembers); - - /* Now generate the table. */ - - if (cd != NULL) - prcode(fp, -"\n" -"static sipEnumMemberDef enummembers_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"/* These are the enum members of all global enums. */\n" -"static sipEnumMemberDef enummembers[] = {\n" - ); - - for (i = 0; i < nr_members; ++i) - { - enumMemberDef *emd; - - emd = etab[i]; - - prcode(fp, -" {%N, ",emd->pyname); - - if (cd != NULL) - { - if (isProtectedEnum(emd->ed)) - prcode(fp,"sip"); - - prcode(fp,"%S::%s",classFQCName(cd),emd->cname); - } - else - prcode(fp,"%s" - ,emd->cname); - - prcode(fp, ", %d},\n", emd->ed->enumnr); - } - - prcode(fp, -"};\n" - ); - - return nr_members; -} - - -/* - * The qsort helper to compare two enumMemberDef structures based on the name - * of the enum member. - */ - -static int compareEnumMembers(const void *m1,const void *m2) -{ - return strcmp((*(enumMemberDef **)m1)->pyname->text, - (*(enumMemberDef **)m2)->pyname->text); -} - - -/* - * Generate the access functions for the variables. - */ -static void generateAccessFunctions(sipSpec *pt,classDef *cd,FILE *fp) -{ - varDef *vd; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - if (vd->accessfunc == NULL) - continue; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - prcode(fp, -"\n" -"\n" -"/* Access function. */\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void *access_%C();}\n" - , vd->fqcname); - - prcode(fp, -"static void *access_%C()\n" -"{\n" - ,vd->fqcname); - - generateCppCodeBlock(vd->accessfunc,fp); - - prcode(fp, -"}\n" - ); - } -} - - -/* - * Generate the inline code to add a set of enum instances to a dictionary. - */ -static void generateEnumsInline(sipSpec *pt, FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - if (vd->module != pt->module) - continue; - - if (vd->type.atype != enum_type) - continue; - - if (needsHandler(vd)) - continue; - - /* Skip enums that don't need inline code. */ - if (generating_c || vd->accessfunc != NULL || vd->type.nrderefs != 0) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -" /* Define the enum instances that have to be added inline. */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" sipAddEnumInstance("); - - if (vd->ecd == NULL) - prcode(fp,"sipModuleDict"); - else - prcode(fp,"(PyObject *)sipClass_%C",classFQCName(vd->ecd)); - - prcode(fp,",%N,(int)%S,sipEnum_%C);\n" - , vd->pyname, vd->fqcname, vd->type.u.ed->fqcname); - } -} - - -/* - * Generate the inline code to add a set of class instances to a dictionary. - */ -static void generateClassesInline(sipSpec *pt,FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - if (vd->module != pt->module) - continue; - - if (vd->type.atype != class_type && vd->type.atype != mapped_type) - continue; - - if (needsHandler(vd)) - continue; - - /* Skip classes that don't need inline code. */ - if (generating_c || vd->accessfunc != NULL || vd->type.nrderefs != 0) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -" /*\n" -" * Define the class and mapped type instances that have to be added\n" -" * inline.\n" -" */\n" - ); - - noIntro = FALSE; - } - - if (vd->type.atype == class_type) - prcode(fp, -" sipAddClassInstance("); - else - prcode(fp, -" sipAddMappedTypeInstance("); - - if (vd->ecd == NULL) - prcode(fp,"sipModuleDict"); - else - prcode(fp,"(PyObject *)sipClass_%C",classFQCName(vd->ecd)); - - prcode(fp,",%N,",vd->pyname); - - if (isConstArg(&vd->type)) - prcode(fp,"const_cast<%b *>(&%S)",&vd->type,vd->fqcname); - else - prcode(fp,"&%S",vd->fqcname); - - if (vd->type.atype == class_type) - prcode(fp, ",sipClass_%C);\n" - , classFQCName(vd->type.u.cd)); - else - prcode(fp, ",sipMappedType_%T);\n" - , &vd->type); - } -} - - -/* - * Generate the code to add a set of class instances to a dictionary. Return - * TRUE if there was at least one. - */ -static int generateClasses(sipSpec *pt,classDef *cd,FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - scopedNameDef *vcname; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (vd->type.atype != class_type) - continue; - - if (needsHandler(vd)) - continue; - - /* - * Skip ordinary C++ class instances which need to be done with - * inline code rather than through a static table. This is - * because C++ does not guarantee the order in which the table - * and the instance will be created. So far this has only been - * seen to be a problem when statically linking SIP generated - * modules on Windows. - */ - if (!generating_c && vd->accessfunc == NULL && vd->type.nrderefs == 0) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the class instances to be added to this type dictionary. */\n" -"static sipClassInstanceDef classInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the class instances to be added to this module dictionary. */\n" -"static sipClassInstanceDef classInstances[] = {\n" - ); - - noIntro = FALSE; - } - - vcname = classFQCName(vd->type.u.cd); - - if (vd->accessfunc != NULL) - { - prcode(fp, -" {%N, (void *)access_%C, &sipClass_%C, SIP_ACCFUNC},\n" - ,vd->pyname,vd->fqcname,vcname); - } - else if (vd->type.nrderefs != 0) - { - prcode(fp, -" {%N, &%S, &sipClass_%C, SIP_INDIRECT},\n" - ,vd->pyname,vd->fqcname,vcname); - } - else if (isConstArg(&vd->type)) - { - prcode(fp, -" {%N, const_cast<%b *>(&%S), &sipClass_%C, 0},\n" - ,vd->pyname,&vd->type,vd->fqcname,vcname); - } - else - { - prcode(fp, -" {%N, &%S, &sipClass_%C, 0},\n" - ,vd->pyname,vd->fqcname,vcname); - } - } - - if (!noIntro) - prcode(fp, -" {0, 0, 0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the code to add a set of void pointers to a dictionary. Return - * TRUE if there was at least one. - */ -static int generateVoidPointers(sipSpec *pt,classDef *cd,FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (vd->type.atype != void_type && vd->type.atype != struct_type) - continue; - - if (needsHandler(vd)) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the void pointers to be added to this type dictionary. */\n" -"static sipVoidPtrInstanceDef voidPtrInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the void pointers to be added to this module dictionary. */\n" -"static sipVoidPtrInstanceDef voidPtrInstances[] = {\n" - ); - - noIntro = FALSE; - } - - if (isConstArg(&vd->type)) - prcode(fp, -" {%N, const_cast<%b *>(%S)},\n" - , vd->pyname, &vd->type, vd->fqcname); - else - prcode(fp, -" {%N, %S},\n" - , vd->pyname, vd->fqcname); - } - - if (!noIntro) - prcode(fp, -" {0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the code to add a set of characters to a dictionary. Return TRUE - * if there was at least one. - */ -static int generateChars(sipSpec *pt,classDef *cd,FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - argType vtype = vd->type.atype; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (!((vtype == sstring_type || vtype == ustring_type || vtype == string_type || vtype == wstring_type) && vd->type.nrderefs == 0)) - continue; - - if (needsHandler(vd)) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the chars to be added to this type dictionary. */\n" -"static sipCharInstanceDef charInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the chars to be added to this module dictionary. */\n" -"static sipCharInstanceDef charInstances[] = {\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" {%N, %S},\n" - ,vd->pyname,vd->fqcname); - } - - if (!noIntro) - prcode(fp, -" {0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the code to add a set of strings to a dictionary. Return TRUE if - * there is at least one. - */ -static int generateStrings(sipSpec *pt,classDef *cd,FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - argType vtype = vd->type.atype; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (!((vtype == sstring_type || vtype == ustring_type || vtype == string_type || vtype == wstring_type) && vd->type.nrderefs != 0)) - continue; - - if (needsHandler(vd)) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the strings to be added to this type dictionary. */\n" -"static sipStringInstanceDef stringInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the strings to be added to this module dictionary. */\n" -"static sipStringInstanceDef stringInstances[] = {\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" {%N, %S},\n" - ,vd->pyname,vd->fqcname); - } - - if (!noIntro) - prcode(fp, -" {0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the code to add a set of enum instances to a dictionary. Return - * TRUE if there was at least one. - */ -static int generateEnums(sipSpec *pt, classDef *cd, FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (vd->type.atype != enum_type || vd->type.u.ed->fqcname == NULL) - continue; - - if (needsHandler(vd)) - continue; - - /* Skip enums that need inline code. */ - if (!generating_c && vd->accessfunc == NULL && vd->type.nrderefs == 0) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the enum instances to be added to this type dictionary. */\n" -"static sipEnumInstanceDef enumInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the enum instances to be added to this module dictionary. */\n" -"static sipEnumInstanceDef enumInstances[] = {\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" {%N, (int)%S, &sipEnum_%C},\n" - ,vd->pyname,vd->fqcname,vd->type.u.ed->fqcname); - } - - if (!noIntro) - prcode(fp, -" {0, 0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the code to add a set of ints to a dictionary. Return TRUE if - * there was at least one. - */ -static int generateInts(sipSpec *pt, classDef *cd, FILE *fp) -{ - int noIntro; - varDef *vd; - enumDef *ed; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - argType vtype = vd->type.atype; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (!(vtype == enum_type || vtype == ushort_type || - vtype == short_type || vtype == uint_type || - vtype == cint_type || vtype == int_type || - vtype == bool_type || vtype == cbool_type)) - continue; - - if (needsHandler(vd)) - continue; - - /* Named enums are handled elsewhere. */ - if (vtype == enum_type && vd->type.u.ed->fqcname != NULL) - continue; - - if (noIntro) - { - ints_intro(cd, fp); - noIntro = FALSE; - } - - prcode(fp, -" {%N, %S},\n" - ,vd->pyname,vd->fqcname); - } - - /* Now do global anonymous enums. */ - if (cd == NULL) - for (ed = pt->enums; ed != NULL; ed = ed->next) - { - enumMemberDef *em; - - if (ed->ecd != cd || ed->module != pt->module) - continue; - - if (ed->fqcname != NULL) - continue; - - for (em = ed->members; em != NULL; em = em->next) - { - if (noIntro) - { - ints_intro(cd, fp); - noIntro = FALSE; - } - - prcode(fp, -" {%N, %s},\n" - , em->pyname, em->cname); - } - } - - if (!noIntro) - prcode(fp, -" {0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the intro for a table of int instances. - */ -static void ints_intro(classDef *cd, FILE *fp) -{ - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the ints to be added to this type dictionary. */\n" -"static sipIntInstanceDef intInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the ints to be added to this module dictionary. */\n" -"static sipIntInstanceDef intInstances[] = {\n" - ); -} - - -/* - * Generate the code to add a set of longs to a dictionary. Return TRUE if - * there was at least one. - */ -static int generateLongs(sipSpec *pt, classDef *cd, FILE *fp) -{ - return generateVariableType(pt, cd, long_type, "long", "Long", "long", fp); -} - - -/* - * Generate the code to add a set of unsigned longs to a dictionary. Return - * TRUE if there was at least one. - */ -static int generateUnsignedLongs(sipSpec *pt, classDef *cd, FILE *fp) -{ - return generateVariableType(pt, cd, ulong_type, "unsigned long", "UnsignedLong", "unsignedLong", fp); -} - - -/* - * Generate the code to add a set of long longs to a dictionary. Return TRUE - * if there was at least one. - */ -static int generateLongLongs(sipSpec *pt, classDef *cd, FILE *fp) -{ - return generateVariableType(pt, cd, longlong_type, "long long", "LongLong", "longLong", fp); -} - - -/* - * Generate the code to add a set of unsigned long longs to a dictionary. - * Return TRUE if there was at least one. - */ -static int generateUnsignedLongLongs(sipSpec *pt, classDef *cd, FILE *fp) -{ - return generateVariableType(pt, cd, ulonglong_type, "unsigned long long", "UnsignedLongLong", "unsignedLongLong", fp); -} - - -/* - * Generate the code to add a set of a particular type to a dictionary. Return - * TRUE if there was at least one. - */ -static int generateVariableType(sipSpec *pt, classDef *cd, argType atype, const char *eng, const char *s1, const char *s2, FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - argType vtype = vd->type.atype; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (vtype != atype) - continue; - - if (needsHandler(vd)) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the %ss to be added to this type dictionary. */\n" -"static sip%sInstanceDef %sInstances_%C[] = {\n" - , eng - , s1, s2, classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the %ss to be added to this module dictionary. */\n" -"static sip%sInstanceDef %sInstances[] = {\n" - , eng - , s1, s2); - - noIntro = FALSE; - } - - prcode(fp, -" {%N, %S},\n" - ,vd->pyname,vd->fqcname); - } - - if (!noIntro) - prcode(fp, -" {0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the code to add a set of doubles to a dictionary. Return TRUE if - * there was at least one. - */ -static int generateDoubles(sipSpec *pt,classDef *cd,FILE *fp) -{ - int noIntro; - varDef *vd; - - noIntro = TRUE; - - for (vd = pt->vars; vd != NULL; vd = vd->next) - { - argType vtype = vd->type.atype; - - if (vd->ecd != cd || vd->module != pt->module) - continue; - - if (!(vtype == float_type || vtype == cfloat_type || vtype == double_type || vtype == cdouble_type)) - continue; - - if (needsHandler(vd)) - continue; - - if (noIntro) - { - if (cd != NULL) - prcode(fp, -"\n" -"\n" -"/* Define the doubles to be added to this type dictionary. */\n" -"static sipDoubleInstanceDef doubleInstances_%C[] = {\n" - ,classFQCName(cd)); - else - prcode(fp, -"\n" -"\n" -"/* Define the doubles to be added to this module dictionary. */\n" -"static sipDoubleInstanceDef doubleInstances[] = {\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" {%N, %S},\n" - ,vd->pyname,vd->fqcname); - } - - if (!noIntro) - prcode(fp, -" {0, 0}\n" -"};\n" - ); - - return !noIntro; -} - - -/* - * Generate the C/C++ code for an interface. - */ -static void generateIfaceCpp(sipSpec *pt,ifaceFileDef *iff,char *codeDir, - char *srcSuffix,FILE *master) -{ - char *cppfile, *cmname = iff->module->name; - classDef *cd; - mappedTypeDef *mtd; - FILE *fp; - - if (master == NULL) - { - cppfile = createIfaceFileName(codeDir,iff,srcSuffix); - fp = createCompilationUnit(pt, cppfile, "Interface wrapper code."); - } - else - fp = master; - - prcode(fp, -"\n" -"#include \"sipAPI%s.h\"\n" -"#include \"sip%s%F.h\"\n" - ,cmname - ,cmname,iff->fqcname); - - generateUsedIncludes(iff->used, FALSE, fp); - - for (cd = pt->classes; cd != NULL; cd = cd->next) - if (cd->iff == iff) - { - if (isProtectedClass(cd)) - prcode(fp, -"\n" -"#include \"sip%s%F.h\"\n" - ,cmname,cd->ecd->iff->fqcname); - - if (!isExternal(cd)) - generateClassCpp(cd, pt, fp); - } - - for (mtd = pt->mappedtypes; mtd != NULL; mtd = mtd->next) - if (mtd->iff == iff) - generateMappedTypeCpp(mtd,fp); - - if (master == NULL) - { - closeFile(fp); - free(cppfile); - } -} - - -/* - * Return a filename for an interface C++ or header file on the heap. - */ -static char *createIfaceFileName(char *codeDir,ifaceFileDef *iff,char *suffix) -{ - char *fn; - scopedNameDef *snd; - - fn = concat(codeDir,"/sip",iff->module->name,NULL); - - for (snd = iff->fqcname; snd != NULL; snd = snd->next) - append(&fn,snd->name); - - append(&fn,suffix); - - return fn; -} - - -/* - * Generate the C++ code for a mapped type version. - */ -static void generateMappedTypeCpp(mappedTypeDef *mtd,FILE *fp) -{ - int need_xfer; - - prcode(fp, -"\n" -"\n" -"/* Call the mapped type's destructor. */\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void release_%T(void *, int);}\n" - , &mtd->type); - - prcode(fp, -"static void release_%T(void *ptr, int%s)\n" -"{\n" - , &mtd->type, (generating_c ? " status" : "")); - - if (release_gil) - prcode(fp, -" Py_BEGIN_ALLOW_THREADS\n" - ); - - if (generating_c) - prcode(fp, -" sipFree(ptr);\n" - ); - else - prcode(fp, -" delete reinterpret_cast<%b *>(ptr);\n" - , &mtd->type); - - if (release_gil) - prcode(fp, -" Py_END_ALLOW_THREADS\n" - ); - - prcode(fp, -"}\n" -"\n" - ); - - generateConvertToDefinitions(mtd,NULL,fp); - - /* Generate the from type convertor. */ - - need_xfer = (generating_c || usedInCode(mtd->convfromcode, "sipTransferObj")); - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static PyObject *convertFrom_%T(void *, PyObject *);}\n" - , &mtd->type); - - prcode(fp, -"static PyObject *convertFrom_%T(void *sipCppV,PyObject *%s)\n" -"{\n" -" ", &mtd->type, (need_xfer ? "sipTransferObj" : "")); - - generateMappedTypeFromVoid(mtd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -"\n" - ); - - generateCppCodeBlock(mtd->convfromcode,fp); - - prcode(fp, -"}\n" -"\n" -"\n" -"sipMappedType sipMappedTypeDef_%T = {\n" -" \"%B\",\n" -" release_%T,\n" -" forceConvertTo_%T,\n" -" convertTo_%T,\n" -" convertFrom_%T\n" -"};\n" - , &mtd->type - , &mtd->type - , &mtd->type - , &mtd->type - , &mtd->type - , &mtd->type - , &mtd->type); -} - - -/* - * Generate the C++ code for a class. - */ -static void generateClassCpp(classDef *cd,sipSpec *pt,FILE *fp) -{ - varDef *vd; - - /* Generate any local class code. */ - - generateCppCodeBlock(cd->cppcode,fp); - - generateClassFunctions(pt,cd,fp); - - generateAccessFunctions(pt,cd,fp); - - /* Generate the variable handlers. */ - if (hasVarHandlers(cd)) - { - for (vd = pt->vars; vd != NULL; vd = vd->next) - if (vd->ecd == cd && needsHandler(vd)) - generateVariableHandler(vd,fp); - - /* Generate the variable table. */ - prcode(fp, -"\n" -"PyMethodDef variables_%C[] = {\n" - ,classFQCName(cd)); - - for (vd = pt->vars; vd != NULL; vd = vd->next) - if (vd->ecd == cd && needsHandler(vd)) - prcode(fp, -" {%N, var_%C, %s, NULL},\n" - ,vd->pyname,vd->fqcname,(isStaticVar(vd) ? "METH_STATIC" : "0")); - - prcode(fp, -" {0, 0, 0, 0}\n" -"};\n" - ); - } - - if (cd->iff->type != namespace_iface) - generateConvertToDefinitions(NULL,cd,fp); - - /* The type definition structure. */ - generateTypeDefinition(pt, cd, fp); -} - - -/* - * Return a sorted array of relevant functions for a namespace. - */ - -static sortedMethTab *createFunctionTable(classDef *cd,int *nrp) -{ - int nr; - sortedMethTab *mtab, *mt; - memberDef *md; - - /* First we need to count the number of applicable functions. */ - - nr = 0; - - for (md = cd->members; md != NULL; md = md->next) - ++nr; - - if ((*nrp = nr) == 0) - return NULL; - - /* Create the table of methods. */ - - mtab = sipMalloc(sizeof (sortedMethTab) * nr); - - /* Initialise the table. */ - - mt = mtab; - - for (md = cd->members; md != NULL; md = md->next) - { - mt->md = md; - mt->is_static = TRUE; - - ++mt; - } - - /* Finally sort the table. */ - - qsort(mtab,nr,sizeof (sortedMethTab),compareMethTab); - - return mtab; -} - - -/* - * Return a sorted array of relevant methods (either lazy or non-lazy) for a - * class. - */ -static sortedMethTab *createMethodTable(classDef *cd, int *nrp) -{ - int nr; - visibleList *vl; - sortedMethTab *mtab, *mt; - - /* - * First we need to count the number of applicable methods. Only provide - * an entry point if there is at least one overload that is defined in this - * class and is a non-abstract function or slot. We allow private (even - * though we don't actually generate code) because we need to intercept the - * name before it reaches a more public version further up the class - * hierarchy. We add the ctor and any variable handlers as special - * entries. - */ - nr = 0; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - overDef *od; - - if (vl->m->slot != no_slot) - continue; - - for (od = vl->cd->overs; od != NULL; od = od->next) - { - /* - * Skip protected methods if we don't have the means to - * handle them. - */ - if (isProtected(od) && !hasShadow(cd)) - continue; - - if (skipOverload(od,vl->m,cd,vl->cd,TRUE)) - continue; - - ++nr; - - break; - } - } - - if ((*nrp = nr) == 0) - return NULL; - - /* Create the table of methods. */ - - mtab = sipMalloc(sizeof (sortedMethTab) * nr); - - /* Initialise the table. */ - - mt = mtab; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - int need_method, is_static; - overDef *od; - - if (vl->m->slot != no_slot) - continue; - - need_method = FALSE; - is_static = TRUE; - - for (od = vl->cd->overs; od != NULL; od = od->next) - { - /* - * Skip protected methods if we don't have the means to - * handle them. - */ - if (isProtected(od) && !hasShadow(cd)) - continue; - - if (!skipOverload(od,vl->m,cd,vl->cd,TRUE)) - { - need_method = TRUE; - - if (!isPrivate(od) && !isStatic(od)) - is_static = FALSE; - } - } - - if (need_method) - { - mt->md = vl->m; - mt->is_static = is_static; - - ++mt; - } - } - - /* Finally sort the table. */ - - qsort(mtab,nr,sizeof (sortedMethTab),compareMethTab); - - return mtab; -} - - -/* - * The qsort helper to compare two sortedMethTab structures based on the Python - * name of the method. - */ - -static int compareMethTab(const void *m1,const void *m2) -{ - return strcmp(((sortedMethTab *)m1)->md->pyname->text, - ((sortedMethTab *)m2)->md->pyname->text); -} - - -/* - * Generate the sorted table of methods and return the number of entries. - */ -static int generateMethodTable(classDef *cd,FILE *fp) -{ - int nr; - sortedMethTab *mtab; - - mtab = (cd->iff->type == namespace_iface) ? - createFunctionTable(cd,&nr) : - createMethodTable(cd,&nr); - - if (mtab != NULL) - { - int i; - - prcode(fp, -"\n" -"\n" -"static PyMethodDef methods_%C[] = {\n" - ,classFQCName(cd)); - - for (i = 0; i < nr; ++i) - { - memberDef *md = mtab[i].md; - - /* - * For the moment we are suppressing the generation of - * METH_STATIC until we understand descriptors better. - * It could be that they will simplify the handling of - * lazy attributes and allow things to be cached in the - * type dictionary. - */ - mtab[i].is_static = FALSE; - - prcode(fp, -" {%N, meth_%C_%s, METH_VARARGS%s, NULL}%s\n" - ,md->pyname,classFQCName(cd),md->pyname->text,(mtab[i].is_static ? "|METH_STATIC" : ""),((i + 1) < nr) ? "," : ""); - } - - free(mtab); - - prcode(fp, -"};\n" - ); - } - - return nr; -} - - -/* - * Generate the "to type" convertor definitions. - */ - -static void generateConvertToDefinitions(mappedTypeDef *mtd,classDef *cd, - FILE *fp) -{ - codeBlock *convtocode; - ifaceFileDef *iff; - argDef type; - - if (cd != NULL) - { - convtocode = cd->convtocode; - - iff = cd->iff; - - type.atype = class_type; - type.u.cd = cd; - } - else - { - convtocode = mtd->convtocode; - - iff = mtd->iff; - - type.atype = mapped_type; - type.u.mtd = mtd; - } - - type.argflags = 0; - type.name = NULL; - type.nrderefs = 0; - type.defval = NULL; - - /* Generate the type convertors. */ - - if (convtocode != NULL) - { - int need_ptr, need_xfer; - - /* - * Sometimes type convertors are just stubs that set the error - * flag, so check if we actually need everything so that we - * can avoid compiler warnings. - */ - need_ptr = (generating_c || usedInCode(convtocode, "sipCppPtr")); - need_xfer = (generating_c || usedInCode(convtocode, "sipTransferObj")); - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static int convertTo_%T(PyObject *, void **, int *, PyObject *);}\n" - , &type); - - prcode(fp, -"static int convertTo_%T(PyObject *sipPy,void **%s,int *sipIsErr,PyObject *%s)\n" -"{\n" - , &type, (need_ptr ? "sipCppPtrV" : ""), (need_xfer ? "sipTransferObj" : "")); - - if (need_ptr) - if (generating_c) - prcode(fp, -" %b **sipCppPtr = (%b **)sipCppPtrV;\n" -"\n" - , &type, &type); - else - prcode(fp, -" %b **sipCppPtr = reinterpret_cast<%b **>(sipCppPtrV);\n" -"\n" - , &type, &type); - - generateCppCodeBlock(convtocode,fp); - - prcode(fp, -"}\n" - ); - } - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void *forceConvertTo_%T(PyObject *, int *);}\n" - , &type); - - prcode(fp, -"static void *forceConvertTo_%T(PyObject *valobj,int *iserrp)\n" -"{\n" -" if (*iserrp || valobj == NULL)\n" -" return NULL;\n" -"\n" - ,&type); - - if (convtocode != NULL) - prcode(fp, -" if (convertTo_%T(valobj,NULL,NULL,NULL))\n" -" {\n" -" void *val;\n" -"\n" -" /*\n" -" * Note that we throw away the flag that says if the value\n" -" * has just been created on the heap or not.\n" -" */\n" -" convertTo_%T(valobj,&val,iserrp,NULL);\n" -"\n" -" return val;\n" -" }\n" - ,&type - ,&type); - else - prcode(fp, -" if (valobj == Py_None || sipIsSubClassInstance(valobj,sipClass_%T))\n" -" return sipConvertToCpp(valobj,sipClass_%T,iserrp);\n" - ,&type - ,&type); - - if (cd != NULL) - prcode(fp, -"\n" -" sipBadClass(%N);\n" - , iff->name); - else - prcode(fp, -"\n" -" sipBadClass(\"%B\");\n" - , &mtd->type); - - prcode(fp, -"\n" -" *iserrp = 1;\n" -"\n" -" return NULL;\n" -"}\n" - ); -} - - -/* - * Generate a variable handler. - */ -static void generateVariableHandler(varDef *vd,FILE *fp) -{ - argType atype = vd->type.atype; - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static PyObject *var_%C(PyObject *, PyObject *);}\n" - , vd->fqcname); - - prcode(fp, -"static PyObject *var_%C(PyObject *%s,PyObject *sipPy)\n" -"{\n" - ,vd->fqcname,(isStaticVar(vd) ? "" : "sipSelf")); - - if (atype == class_type || atype == mapped_type) - prcode(fp, -" int sipIsErr = 0;\n" - ); - - if (vd->type.nrderefs == 0 && (atype == mapped_type || (atype == class_type && vd->type.u.cd->convtocode != NULL))) - prcode(fp, -" int sipValState;\n" - ); - - if (vd->getcode == NULL || vd->setcode == NULL) - { - prcode(fp, -" "); - - generateNamedValueType(&vd->type, "sipVal", fp); - - prcode(fp, ";\n" - ); - } - - if (!isStaticVar(vd)) - { - if (generating_c) - prcode(fp, -" %S *sipCpp = (%S *)sipGetCppPtr((sipWrapper *)sipSelf,sipClass_%C);\n" - ,classFQCName(vd->ecd),classFQCName(vd->ecd),classFQCName(vd->ecd)); - else - prcode(fp, -" %S *sipCpp = reinterpret_cast<%S *>(sipGetCppPtr((sipWrapper *)sipSelf,sipClass_%C));\n" - ,classFQCName(vd->ecd),classFQCName(vd->ecd),classFQCName(vd->ecd)); - - prcode(fp, -"\n" -" if (!sipCpp)\n" -" return NULL;\n" - ); - } - - prcode(fp, -"\n" -" if (sipPy == NULL)\n" -" {\n" - ); - - /* Generate the get handler part. */ - - if (vd->getcode != NULL) - { - generateCppCodeBlock(vd->getcode, fp); - - prcode(fp, -"\n" -" return sipPy;\n" - ); - } - else - { - int pyobj = FALSE; - - prcode(fp, -" sipVal = %s", (((atype == class_type || atype == mapped_type) && vd->type.nrderefs == 0) ? "&" : "")); - - generateVarMember(vd, fp); - - prcode(fp, ";\n" -"\n" - ); - - switch (atype) - { - case mapped_type: - prcode(fp, -" sipPy = sipConvertFromMappedType(sipVal,sipMappedType_%T,NULL);\n" - ,&vd->type); - - break; - - case class_type: - generateVarClassConversion(vd,fp); - break; - - case bool_type: - case cbool_type: - prcode(fp, -" sipPy = PyBool_FromLong(sipVal);\n" - ); - - break; - - case sstring_type: - case ustring_type: - case string_type: - if (vd->type.nrderefs == 0) - prcode(fp, -" sipPy = PyString_FromStringAndSize(%s&sipVal,1);\n" - ,(atype != string_type) ? "(char *)" : ""); - else - prcode(fp, -" sipPy = PyString_FromString(%ssipVal);\n" - ,(atype != string_type) ? "(char *)" : ""); - - break; - - case wstring_type: - if (vd->type.nrderefs == 0) - prcode(fp, -" sipPy = PyUnicode_FromWideChar(&sipVal,1);\n" - ); - else - prcode(fp, -" sipPy = PyUnicode_FromWideChar(sipVal,(SIP_SSIZE_T)wcslen(sipVal));\n" - ); - - break; - - case float_type: - case cfloat_type: - prcode(fp, -" sipPy = PyFloat_FromDouble((double)sipVal);\n" - ); - break; - - case double_type: - case cdouble_type: - prcode(fp, -" sipPy = PyFloat_FromDouble(sipVal);\n" - ); - break; - - case enum_type: - if (vd->type.u.ed->fqcname != NULL) - { - prcode(fp, -" sipPy = sipConvertFromNamedEnum(sipVal,sipEnum_%C);\n" - ,vd->type.u.ed->fqcname); - - break; - } - - /* Drop through. */ - - case short_type: - case cint_type: - case int_type: - prcode(fp, -" sipPy = PyInt_FromLong(sipVal);\n" - ); - break; - - case long_type: - prcode(fp, -" sipPy = PyLong_FromLong(sipVal);\n" - ); - break; - - case ushort_type: - case uint_type: - case ulong_type: - prcode(fp, -" sipPy = PyLong_FromUnsignedLong(sipVal);\n" - ); - break; - - case longlong_type: - prcode(fp, -" sipPy = PyLong_FromLongLong(sipVal);\n" - ); - break; - - case ulonglong_type: - prcode(fp, -" sipPy = PyLong_FromUnsignedLongLong(sipVal);\n" - ); - break; - - case struct_type: - prcode(fp, -" sipPy = sipConvertFromVoidPtr("); - - if (isConstArg(&vd->type)) - prcode(fp, "const_cast<%b *>(sipVal)", &vd->type); - else - prcode(fp, "sipVal"); - - prcode(fp, ");\n" - ); - - break; - - case void_type: - prcode(fp, -" sipPy = sipConvertFromVoidPtr("); - - if (isConstArg(&vd->type)) - prcode(fp, "const_cast<void *>(sipVal)"); - else - prcode(fp, "sipVal"); - - prcode(fp, ");\n" - ); - - break; - - case pyobject_type: - case pytuple_type: - case pylist_type: - case pydict_type: - case pycallable_type: - case pyslice_type: - case pytype_type: - prcode(fp, -" Py_XINCREF(sipVal);\n" - ); - pyobj = TRUE; - break; - } - - prcode(fp, -"\n" -" return %s;\n" - ,(pyobj ? "sipVal" : "sipPy")); - } - - prcode(fp, -" }\n" -"\n" - ); - - /* Generate the set handler part. */ - - if (vd->setcode != NULL) - { - prcode(fp, -" {\n" -" int sipErr = 0;\n" -"\n" - ); - - generateCppCodeBlock(vd->setcode, fp); - - prcode(fp, -"\n" -" if (sipErr)\n" -" return NULL;\n" -" }\n" - ); - } - else - { - char *deref; - int might_be_temp; - - might_be_temp = generateObjToCppConversion(&vd->type,fp); - - deref = ""; - - if (atype == class_type || atype == mapped_type) - { - if (vd->type.nrderefs == 0) - deref = "*"; - - prcode(fp, -"\n" -" if (sipIsErr)\n" -" return NULL;\n" -"\n" - ); - } - else - { - if ((atype == sstring_type || atype == ustring_type || atype == string_type || atype == wstring_type) && vd->type.nrderefs != 0) - { - prcode(fp, -"\n" -" if (sipVal == NULL)\n" - ); - } - else - prcode(fp, -"\n" -" if (PyErr_Occurred() != NULL)\n" - ); - - prcode(fp, -" {\n" -" sipBadSetType(%N,%N);\n" -" return NULL;\n" -" }\n" -"\n" - ,vd->ecd->iff->name,vd->pyname); - } - - if (atype == pyobject_type || atype == pytuple_type || - atype == pylist_type || atype == pydict_type || - atype == pycallable_type || atype == pyslice_type || - atype == pytype_type) - { - prcode(fp, -" Py_XDECREF("); - - generateVarMember(vd, fp); - - prcode(fp, ");\n" -" Py_INCREF(sipVal);\n" -"\n" - ); - } - - prcode(fp, -" "); - - generateVarMember(vd, fp); - - prcode(fp, " = %ssipVal;\n" - , deref); - - /* Note that wchar_t * leaks here. */ - - if (might_be_temp) - prcode(fp, -"\n" -" sipReleaseInstance(sipVal,sipClass_%C,sipValState);\n" - , classFQCName(vd->type.u.cd)); - else if (vd->type.atype == mapped_type && vd->type.nrderefs == 0) - prcode(fp, -"\n" -" sipReleaseMappedType(sipVal,sipMappedType_%T,sipValState);\n" - , &vd->type); - } - - prcode(fp, -"\n" -" Py_INCREF(Py_None);\n" -" return Py_None;\n" -"}\n" - ); -} - - -/* - * Generate the member variable of a class. - */ -static void generateVarMember(varDef *vd, FILE *fp) -{ - if (isStaticVar(vd)) - prcode(fp,"%S::",classFQCName(vd->ecd)); - else - prcode(fp,"sipCpp->"); - - prcode(fp, "%s", scopedNameTail(vd->fqcname)); -} - - -/* - * Generate an variable class conversion fragment. - */ -static void generateVarClassConversion(varDef *vd,FILE *fp) -{ - classDef *cd = vd->type.u.cd; - - prcode(fp, -" sipPy = sipConvertFromInstance("); - - if (isConstArg(&vd->type)) - prcode(fp,"const_cast<%b *>(sipVal)",&vd->type); - else - prcode(fp,"sipVal"); - - prcode(fp,",sipClass_%C,NULL);\n" - ,classFQCName(cd)); -} - - -/* - * Generate the declaration of a variable that is initialised from a Python - * object. Return TRUE if the value might be a temporary on the heap. - */ -static int generateObjToCppConversion(argDef *ad,FILE *fp) -{ - int might_be_temp = FALSE; - char *rhs = NULL; - - prcode(fp, -" sipVal = "); - - switch (ad->atype) - { - case mapped_type: - { - const char *tail; - - if (generating_c) - { - prcode(fp, "(%b *)", ad); - tail = ""; - } - else - { - prcode(fp, "reinterpret_cast<%b *>(", ad); - tail = ")"; - } - - /* - * Note that we don't support /Transfer/ but could do. - */ - - prcode(fp, "sipForceConvertToMappedType(sipPy,sipMappedType_%T,NULL,%s,%s,&sipIsErr)", ad, (ad->nrderefs ? "0" : "SIP_NOT_NONE"), (ad->nrderefs ? "NULL" : "&sipValState")); - - prcode(fp, "%s;\n" - , tail); - } - break; - - case class_type: - { - const char *tail; - - if (ad->nrderefs == 0 && ad->u.cd->convtocode != NULL) - might_be_temp = TRUE; - - if (generating_c) - { - prcode(fp, "(%b *)", ad); - tail = ""; - } - else - { - prcode(fp, "reinterpret_cast<%b *>(", ad); - tail = ")"; - } - - /* - * Note that we don't support /Transfer/ but could do. - * We could also support /Constrained/ (so long as we - * also supported it for all types). - */ - - prcode(fp, "sipForceConvertToInstance(sipPy,sipClass_%C,NULL,%s,%s,&sipIsErr)", classFQCName(ad->u.cd), (ad->nrderefs ? "0" : "SIP_NOT_NONE"), (might_be_temp ? "&sipValState" : "NULL")); - - prcode(fp, "%s;\n" - , tail); - } - break; - - case enum_type: - prcode(fp, "(%E)PyInt_AsLong(sipPy);\n" - , ad->u.ed); - break; - - case sstring_type: - if (ad->nrderefs == 0) - rhs = "(signed char)sipString_AsChar(sipPy)"; - else - rhs = "(signed char *)PyString_AsString(sipPy)"; - break; - - case ustring_type: - if (ad->nrderefs == 0) - rhs = "(unsigned char)sipString_AsChar(sipPy)"; - else - rhs = "(unsigned char *)PyString_AsString(sipPy)"; - break; - - case string_type: - if (ad->nrderefs == 0) - rhs = "sipString_AsChar(sipPy)"; - else - rhs = "PyString_AsString(sipPy)"; - break; - - case wstring_type: - if (ad->nrderefs == 0) - rhs = "sipUnicode_AsWChar(sipPy)"; - else - rhs = "sipUnicode_AsWString(sipPy)"; - break; - - case float_type: - case cfloat_type: - rhs = "(float)PyFloat_AsDouble(sipPy)"; - break; - - case double_type: - case cdouble_type: - rhs = "PyFloat_AsDouble(sipPy)"; - break; - - case bool_type: - case cbool_type: - rhs = "(bool)PyInt_AsLong(sipPy)"; - break; - - case ushort_type: - rhs = "(unsigned short)sipLong_AsUnsignedLong(sipPy)"; - break; - - case short_type: - rhs = "(short)PyInt_AsLong(sipPy)"; - break; - - case uint_type: - rhs = "(unsigned)sipLong_AsUnsignedLong(sipPy)"; - break; - - case int_type: - case cint_type: - rhs = "(int)PyInt_AsLong(sipPy)"; - break; - - case ulong_type: - rhs = "sipLong_AsUnsignedLong(sipPy)"; - break; - - case long_type: - rhs = "PyLong_AsLong(sipPy)"; - break; - - case ulonglong_type: - rhs = "PyLong_AsUnsignedLongLong(sipPy)"; - break; - - case longlong_type: - rhs = "PyLong_AsLongLong(sipPy)"; - break; - - case struct_type: - prcode(fp, "(struct %S *)sipConvertToVoidPtr(sipPy);\n" - , ad->u.sname); - break; - - case void_type: - rhs = "sipConvertToVoidPtr(sipPy)"; - break; - - case pyobject_type: - case pytuple_type: - case pylist_type: - case pydict_type: - case pycallable_type: - case pyslice_type: - case pytype_type: - rhs = "sipPy"; - break; - } - - if (rhs != NULL) - prcode(fp, "%s;\n" - , rhs); - - return might_be_temp; -} - - -/* - * Returns TRUE if the given method is a slot that takes zero arguments. - */ -static int isZeroArgSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == str_slot || st == int_slot || st == long_slot || - st == float_slot || st == invert_slot || st == neg_slot || - st == len_slot || st == nonzero_slot || st == pos_slot || - st == abs_slot || st == repr_slot || st == hash_slot); -} - - -/* - * Returns TRUE if the given method is a slot that takes more than one - * argument. - */ -static int isMultiArgSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == setitem_slot || st == call_slot); -} - - -/* - * Returns TRUE if the given method is a slot that returns void (ie. nothing - * other than an error indicator). - */ -int isVoidReturnSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == setitem_slot || st == delitem_slot); -} - - -/* - * Returns TRUE if the given method is a slot that returns int. - */ -int isIntReturnSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == len_slot || st == nonzero_slot || st == contains_slot || - st == cmp_slot); -} - - -/* - * Returns TRUE if the given method is a slot that returns long. - */ -int isLongReturnSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == hash_slot); -} - - -/* - * Returns TRUE if the given method is a slot that takes an int argument. - */ -static int isIntArgSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == repeat_slot || st == irepeat_slot); -} - - -/* - * Returns TRUE if the given method is an inplace number slot. - */ -static int isInplaceNumberSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == iadd_slot || st == isub_slot || st == imul_slot || - st == idiv_slot || st == imod_slot || - st == ior_slot || st == ixor_slot || st == iand_slot || - st == ilshift_slot || st == irshift_slot); -} - - -/* - * Returns TRUE if the given method is an inplace sequence slot. - */ -static int isInplaceSequenceSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == iconcat_slot || st == irepeat_slot); -} - - -/* - * Returns TRUE if the given method is a number slot slot. - */ -int isNumberSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == add_slot || st == sub_slot || st == mul_slot || - st == div_slot || st == mod_slot || - st == and_slot || st == or_slot || st == xor_slot || - st == lshift_slot || st == rshift_slot); -} - - -/* - * Returns TRUE if the given method is a rich compare slot. - */ -int isRichCompareSlot(memberDef *md) -{ - slotType st = md->slot; - - return (st == lt_slot || st == le_slot || st == eq_slot || - st == ne_slot || st == gt_slot || st == ge_slot); -} - - -/* - * Generate a Python slot handler for either a class, an enum or an extender. - */ -static void generateSlot(sipSpec *pt, classDef *cd, enumDef *ed, memberDef *md, FILE *fp) -{ - char *arg_str, *prefix, *ret_type; - int ret_int, nr_args; - overDef *od, *overs; - scopedNameDef *fqcname; - nameDef *pyname; - - if (ed != NULL) - { - prefix = "Enum"; - pyname = ed->pyname; - fqcname = ed->fqcname; - overs = ed->overs; - } - else if (cd != NULL) - { - prefix = "Class"; - pyname = cd->iff->name; - fqcname = classFQCName(cd); - overs = cd->overs; - } - else - { - prefix = NULL; - pyname = NULL; - fqcname = NULL; - overs = pt->overs; - } - - if (isVoidReturnSlot(md) || isIntReturnSlot(md)) - { - ret_int = TRUE; - ret_type = "int "; - } - else - { - ret_int = FALSE; - - if (isLongReturnSlot(md)) - ret_type = "long "; - else - ret_type = "PyObject *"; - } - - if (isIntArgSlot(md)) - { - nr_args = 0; - arg_str = "PyObject *sipSelf,int a0"; - } - else if (isMultiArgSlot(md)) - { - nr_args = 2; - arg_str = "PyObject *sipSelf,PyObject *sipArgs"; - } - else if (isZeroArgSlot(md)) - { - nr_args = 0; - arg_str = "PyObject *sipSelf"; - } - else if (isNumberSlot(md)) - { - nr_args = 2; - arg_str = "PyObject *sipArg0,PyObject *sipArg1"; - } - else - { - nr_args = 1; - arg_str = "PyObject *sipSelf,PyObject *sipArg"; - } - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - { - prcode(fp, -"extern \"C\" {static %sslot_", ret_type); - - if (fqcname != NULL) - prcode(fp, "%C_", fqcname); - - prcode(fp, "%s(%s);}\n" - , md->pyname->text, arg_str); - } - - prcode(fp, -"static %sslot_", ret_type); - - if (fqcname != NULL) - prcode(fp, "%C_", fqcname); - - prcode(fp, "%s(%s)\n" -"{\n" - , md->pyname->text, arg_str); - - if (isInplaceNumberSlot(md)) - prcode(fp, -" if (!PyObject_TypeCheck(sipSelf,(PyTypeObject *)sip%s_%C))\n" -" {\n" -" Py_INCREF(Py_NotImplemented);\n" -" return Py_NotImplemented;\n" -" }\n" -"\n" - , prefix, fqcname); - - if (!isNumberSlot(md)) - if (cd != NULL) - prcode(fp, -" %S *sipCpp = reinterpret_cast<%S *>(sipGetCppPtr((sipWrapper *)sipSelf,sipClass_%C));\n" -"\n" -" if (!sipCpp)\n" -" return %s;\n" -"\n" - , fqcname, fqcname, fqcname - , (md->slot == cmp_slot ? "-2" : (ret_int ? "-1" : "0"))); - else - prcode(fp, -" %S sipCpp = static_cast<%S>(PyInt_AsLong(sipSelf));\n" -"\n" - , fqcname, fqcname); - - if (nr_args > 0) - prcode(fp, -" int sipArgsParsed = 0;\n" - ); - - for (od = overs; od != NULL; od = od->next) - if (od->common == md && isAbstract(od)) - { - prcode(fp, -" bool sipSelfWasArg = !sipSelf;\n" - ); - - break; - } - - for (od = overs; od != NULL; od = od->next) - if (od->common == md) - generateFunctionBody(pt, od, cd, cd, (ed == NULL && !dontDerefSelf(od)), fp); - - if (nr_args > 0) - switch (md->slot) - { - case cmp_slot: - prcode(fp, -"\n" -" return 2;\n" - ); - break; - - case concat_slot: - case iconcat_slot: - case repeat_slot: - case irepeat_slot: - prcode(fp, -"\n" -" /* Raise an exception if the argument couldn't be parsed. */\n" -" sipBadOperatorArg(sipSelf,sipArg,%s);\n" -"\n" -" return NULL;\n" - ,slotName(md->slot)); - break; - - default: - if (isNumberSlot(md) || isRichCompareSlot(md)) - { - /* We can't extend enum slots. */ - if (cd == NULL) - prcode(fp, -"\n" -" Py_INCREF(Py_NotImplemented);\n" -" return Py_NotImplemented;\n" - ); - else if (isNumberSlot(md)) - prcode(fp, -"\n" -" return sipPySlotExtend(&sipModuleAPI_%s,%s,NULL,sipArg0,sipArg1);\n" - , pt->module->name, slotName(md->slot)); - else - prcode(fp, -"\n" -" return sipPySlotExtend(&sipModuleAPI_%s,%s,sip%s_%C,sipSelf,sipArg);\n" - , pt->module->name, slotName(md->slot), prefix, fqcname); - } - else if (isInplaceNumberSlot(md)) - prcode(fp, -"\n" -" PyErr_Clear();\n" -"\n" -" Py_INCREF(Py_NotImplemented);\n" -" return Py_NotImplemented;\n" - ); - else - prcode(fp, -"\n" -" /* Raise an exception if the arguments couldn't be parsed. */\n" -" sipNoMethod(sipArgsParsed,%N,%N);\n" -"\n" -" return %s;\n" - , pyname, md->pyname - ,ret_int ? "-1" : "0"); - } - - prcode(fp, -"}\n" - ); -} - - -/* - * Generate the member functions for a class. - */ -static void generateClassFunctions(sipSpec *pt,classDef *cd,FILE *fp) -{ - visibleList *vl; - memberDef *md; - - /* Any shadow code. */ - if (hasShadow(cd)) - generateShadowCode(pt,cd,fp); - - /* The member functions. */ - for (vl = cd->visible; vl != NULL; vl = vl->next) - if (vl->m->slot == no_slot) - generateFunction(pt, vl->m, vl->cd->overs, cd, vl->cd, fp); - - /* The slot functions. */ - for (md = cd->members; md != NULL; md = md->next) - if (cd->iff->type == namespace_iface) - generateOrdinaryFunction(pt,cd,md,fp); - else if (md->slot != no_slot && md->slot != unicode_slot) - generateSlot(pt, cd, NULL, md, fp); - - if (cd->iff->type != namespace_iface && !generating_c) - { - classList *cl; - int need_ptr, need_state; - - /* The cast function. */ - prcode(fp, -"\n" -"\n" -"/* Cast a pointer to a type somewhere in its superclass hierarchy. */\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void *cast_%C(void *, sipWrapperType *);}\n" - , classFQCName(cd)); - - prcode(fp, -"static void *cast_%C(void *ptr,sipWrapperType *targetClass)\n" -"{\n" - ,classFQCName(cd)); - - if (cd->supers != NULL) - prcode(fp, -" void *res;\n" -"\n" - ); - - prcode(fp, -" if (targetClass == sipClass_%C)\n" -" return ptr;\n" - ,classFQCName(cd)); - - for (cl = cd->supers; cl != NULL; cl = cl->next) - { - scopedNameDef *sname = cl->cd->iff->fqcname; - - prcode(fp, -"\n" -" if ((res = sipCast_%C((%S *)(%S *)ptr,targetClass)) != NULL)\n" -" return res;\n" - ,sname,sname,classFQCName(cd)); - } - - prcode(fp, -"\n" -" return NULL;\n" -"}\n" - ); - - /* Generate the release function without compiler warnings. */ - need_ptr = need_state = FALSE; - - if (canCreate(cd) || isPublicDtor(cd)) - { - if (hasShadow(cd)) - need_ptr = need_state = TRUE; - else if (isPublicDtor(cd)) - need_ptr = TRUE; - } - - prcode(fp, -"\n" -"\n" -"/* Call the instance's destructor. */\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void release_%C(void *, int);}\n" - , classFQCName(cd)); - - prcode(fp, -"static void release_%C(void *%s,int%s)\n" -"{\n" - , classFQCName(cd), (need_ptr ? "ptr" : ""), (need_state ? " state" : "")); - - /* - * If there is an explicit public dtor then assume there is - * some way to call it which we haven't worked out (because we - * don't fully understand C++). - */ - if (canCreate(cd) || isPublicDtor(cd)) - { - int rgil = ((release_gil || isReleaseGILDtor(cd)) && !isHoldGILDtor(cd)); - - if (rgil) - prcode(fp, -" Py_BEGIN_ALLOW_THREADS\n" -"\n" - ); - - if (hasShadow(cd)) - { - prcode(fp, -" if (state & SIP_DERIVED_CLASS)\n" -" delete reinterpret_cast<sip%C *>(ptr);\n" - , classFQCName(cd)); - - if (isPublicDtor(cd)) - prcode(fp, -" else\n" -" delete reinterpret_cast<%U *>(ptr);\n" - , cd); - } - else if (isPublicDtor(cd)) - prcode(fp, -" delete reinterpret_cast<%U *>(ptr);\n" - , cd); - - if (rgil) - prcode(fp, -"\n" -" Py_END_ALLOW_THREADS\n" - ); - } - - prcode(fp, -"}\n" - ); - } - - /* The traverse function. */ - if (cd->travcode != NULL) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static int traverse_%C(void *, visitproc, void *);}\n" - , classFQCName(cd)); - - prcode(fp, -"static int traverse_%C(void *sipCppV,visitproc sipVisit,void *sipArg)\n" -"{\n" -" ", classFQCName(cd)); - - generateClassFromVoid(cd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -" int sipRes;\n" -"\n" - ); - - generateCppCodeBlock(cd->travcode, fp); - - prcode(fp, -"\n" -" return sipRes;\n" -"}\n" - ); - } - - /* The clear function. */ - if (cd->clearcode != NULL) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static int clear_%C(void *);}\n" - , classFQCName(cd)); - - prcode(fp, -"static int clear_%C(void *sipCppV)\n" -"{\n" -" ", classFQCName(cd)); - - generateClassFromVoid(cd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -" int sipRes;\n" -"\n" - ); - - generateCppCodeBlock(cd->clearcode, fp); - - prcode(fp, -"\n" -" return sipRes;\n" -"}\n" - ); - } - - /* The buffer interface functions. */ - if (cd->readbufcode != NULL) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static SIP_SSIZE_T getreadbuffer_%C(PyObject *, void *, SIP_SSIZE_T, void **);}\n" - , classFQCName(cd)); - - prcode(fp, -"static SIP_SSIZE_T getreadbuffer_%C(PyObject *%s, void *sipCppV, SIP_SSIZE_T %s, void **%s)\n" -"{\n" -" ", classFQCName(cd) - , argName("sipSelf", cd->readbufcode) - , argName("sipSegment", cd->readbufcode) - , argName("sipPtrPtr", cd->readbufcode)); - - generateClassFromVoid(cd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -" SIP_SSIZE_T sipRes;\n" -"\n" - ); - - generateCppCodeBlock(cd->readbufcode, fp); - - prcode(fp, -"\n" -" return sipRes;\n" -"}\n" - ); - } - - if (cd->writebufcode != NULL) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static SIP_SSIZE_T getwritebuffer_%C(PyObject *, void *, SIP_SSIZE_T, void **);}\n" - , classFQCName(cd)); - - prcode(fp, -"static SIP_SSIZE_T getwritebuffer_%C(PyObject *%s, void *sipCppV, SIP_SSIZE_T %s, void **%s)\n" -"{\n" -" ", classFQCName(cd) - , argName("sipSelf", cd->writebufcode) - , argName("sipSegment", cd->writebufcode) - , argName("sipPtrPtr", cd->writebufcode)); - - generateClassFromVoid(cd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -" SIP_SSIZE_T sipRes;\n" -"\n" - ); - - generateCppCodeBlock(cd->writebufcode, fp); - - prcode(fp, -"\n" -" return sipRes;\n" -"}\n" - ); - } - - if (cd->segcountcode != NULL) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static SIP_SSIZE_T getsegcount_%C(PyObject *, void *, SIP_SSIZE_T *);}\n" - , classFQCName(cd)); - - prcode(fp, -"static SIP_SSIZE_T getsegcount_%C(PyObject *%s, void *sipCppV, SIP_SSIZE_T *%s)\n" -"{\n" -" ", classFQCName(cd) - , argName("sipSelf", cd->segcountcode) - , argName("sipLenPtr", cd->segcountcode)); - - generateClassFromVoid(cd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -" SIP_SSIZE_T sipRes;\n" -"\n" - ); - - generateCppCodeBlock(cd->segcountcode, fp); - - prcode(fp, -"\n" -" return sipRes;\n" -"}\n" - ); - } - - if (cd->charbufcode != NULL) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static SIP_SSIZE_T getcharbuffer_%C(PyObject *, void *, SIP_SSIZE_T, void **);}\n" - , classFQCName(cd)); - - prcode(fp, -"static SIP_SSIZE_T getcharbuffer_%C(PyObject *%s, void *sipCppV, SIP_SSIZE_T %s, void **%s)\n" -"{\n" -" ", classFQCName(cd) - , argName("sipSelf", cd->charbufcode) - , argName("sipSegment", cd->charbufcode) - , argName("sipPtrPtr", cd->charbufcode)); - - generateClassFromVoid(cd, "sipCpp", "sipCppV", fp); - - prcode(fp, ";\n" -" SIP_SSIZE_T sipRes;\n" -"\n" - ); - - generateCppCodeBlock(cd->charbufcode, fp); - - prcode(fp, -"\n" -" return sipRes;\n" -"}\n" - ); - } - - /* The dealloc function. */ - if (needDealloc(cd)) - { - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void dealloc_%C(sipWrapper *);}\n" - , classFQCName(cd)); - - prcode(fp, -"static void dealloc_%C(sipWrapper *sipSelf)\n" -"{\n" - ,classFQCName(cd)); - - if (tracing) - prcode(fp, -" sipTrace(SIP_TRACE_DEALLOCS,\"dealloc_%C()\\n\");\n" -"\n" - ,classFQCName(cd)); - - /* Disable the virtual handlers. */ - if (hasShadow(cd)) - prcode(fp, -" if (sipIsDerived(sipSelf))\n" -" reinterpret_cast<sip%C *>(sipSelf->u.cppPtr)->sipPySelf = NULL;\n" -"\n" - ,classFQCName(cd)); - - if (generating_c || isPublicDtor(cd) || (hasShadow(cd) && isProtectedDtor(cd))) - { - prcode(fp, -" if (sipIsPyOwned(sipSelf))\n" -" {\n" - ); - - if (cd->dealloccode != NULL) - { - if (usedInCode(cd->dealloccode, "sipCpp")) - { - prcode(fp, -" "); - - generateClassFromVoid(cd, "sipCpp", "sipSelf->u.cppPtr", fp); - - prcode(fp, ";\n" - ); - } - - generateCppCodeBlock(cd->dealloccode,fp); - - prcode(fp, -"\n" - ); - } - - if (isDelayedDtor(cd)) - prcode(fp, -" sipAddDelayedDtor(sipSelf);\n" - ); - else if (generating_c) - prcode(fp, -" sipFree(sipSelf->u.cppPtr);\n" - ); - else - prcode(fp, -" release_%C(sipSelf->u.cppPtr,%s);\n" - , classFQCName(cd), (hasShadow(cd) ? "sipSelf->flags" : "0")); - - prcode(fp, -" }\n" - ); - } - - prcode(fp, -"}\n" - ); - } - - /* The type initialisation function. */ - if (canCreate(cd)) - generateTypeInit(pt, cd, fp); -} - - -/* - * Generate the shadow (derived) class code. - */ -static void generateShadowCode(sipSpec *pt,classDef *cd,FILE *fp) -{ - int nrVirts, virtNr; - virtOverDef *vod; - ctorDef *ct; - - nrVirts = countVirtuals(cd); - - /* Generate the wrapper class constructors. */ - - for (ct = cd->ctors; ct != NULL; ct = ct->next) - { - char *prefix; - int a; - ctorDef *dct; - - if (isPrivateCtor(ct)) - continue; - - if (ct->cppsig == NULL) - continue; - - /* Check we haven't already handled this C++ signature. */ - for (dct = cd->ctors; dct != ct; dct = dct->next) - if (dct->cppsig != NULL && sameSignature(dct->cppsig, ct->cppsig, TRUE)) - break; - - if (dct != ct) - continue; - - prcode(fp, -"\n" -"sip%C::sip%C(",classFQCName(cd),classFQCName(cd)); - - generateArgs(ct->cppsig,Definition,fp); - - prcode(fp,")%X: %S(",ct->exceptions,classFQCName(cd)); - - prefix = ""; - - for (a = 0; a < ct->cppsig->nrArgs; ++a) - { - prcode(fp,"%sa%d",prefix,a); - prefix = ","; - } - - prcode(fp,"), sipPySelf(0)\n" -"{\n" - ); - - if (tracing) - { - prcode(fp, -" sipTrace(SIP_TRACE_CTORS,\"sip%C::sip%C(",classFQCName(cd),classFQCName(cd)); - generateArgs(ct->cppsig,Declaration,fp); - prcode(fp,")%X (this=0x%%08x)\\n\",this);\n" -"\n" - ,ct->exceptions); - } - - prcode(fp, -" sipCommonCtor(%s,%d);\n" -"}\n" - ,(nrVirts > 0 ? "sipPyMethods" : "NULL"),nrVirts); - } - - /* The destructor. */ - - if (!isPrivateDtor(cd)) - { - prcode(fp, -"\n" -"sip%C::~sip%C()%X\n" -"{\n" - ,classFQCName(cd),classFQCName(cd),cd->dtorexceptions); - - if (tracing) - prcode(fp, -" sipTrace(SIP_TRACE_DTORS,\"sip%C::~sip%C()%X (this=0x%%08x)\\n\",this);\n" -"\n" - ,classFQCName(cd),classFQCName(cd),cd->dtorexceptions); - - if (cd->dtorcode != NULL) - generateCppCodeBlock(cd->dtorcode,fp); - - prcode(fp, -" sipCommonDtor(sipPySelf);\n" -"}\n" - ); - } - - /* The metacall method if required. */ - if (isQObjectSubClass(cd) && optQ_OBJECT4(pt)) - { - prcode(fp, -"\n" -"const TQMetaObject *sip%C::metaObject() const\n" -"{\n" -" return sip_%s_qt_metaobject(sipPySelf,sipClass_%C,%S::metaObject());\n" -"}\n" -"\n" -"int sip%C::qt_metacall(TQMetaObject::Call _c,int _id,void **_a)\n" -"{\n" -" sip%C::metaObject();\n" -"\n" -" _id = %S::qt_metacall(_c,_id,_a);\n" -"\n" -" if (_id >= 0)\n" -" {\n" -" SIP_BLOCK_THREADS\n" -" _id = sip_%s_qt_metacall(sipPySelf,sipClass_%C,_c,_id,_a);\n" -" SIP_UNBLOCK_THREADS\n" -" }\n" -"\n" -" return _id;\n" -"}\n" - , classFQCName(cd) - , pt->module->name, classFQCName(cd), classFQCName(cd) - , classFQCName(cd) - , classFQCName(cd) - , classFQCName(cd) - , pt->module->name, classFQCName(cd)); - } - - /* Generate the virtual catchers. */ - - virtNr = 0; - - for (vod = cd->vmembers; vod != NULL; vod = vod->next) - { - overDef *od = &vod->o; - virtOverDef *dvod; - - if (isPrivate(od)) - continue; - - /* Check we haven't already handled this C++ signature. */ - for (dvod = cd->vmembers; dvod != vod; dvod = dvod->next) - if (strcmp(dvod->o.cppname,od->cppname) == 0 && sameSignature(dvod->o.cppsig,od->cppsig,TRUE)) - break; - - if (dvod != vod) - continue; - - generateVirtualCatcher(pt,cd,virtNr++,vod,fp); - } - - /* Generate the wrapper around each protected member function. */ - - generateProtectedDefinitions(cd,fp); - - /* Generate the emitters if needed. */ - if (!optNoEmitters(pt)) - generateEmitters(pt, cd, fp); -} - - -/* - * Generate the emitter functions. - */ -static void generateEmitters(sipSpec *pt, classDef *cd, FILE *fp) -{ - int noIntro; - visibleList *vl; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - overDef *od; - - for (od = vl->cd->overs; od != NULL; od = od->next) - if (od->common == vl->m && isSignal(od)) - { - generateEmitter(pt,cd,vl,fp); - break; - } - } - - /* Generate the table of signals to support fan-outs. */ - - noIntro = TRUE; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - overDef *od; - - for (od = vl->cd->overs; od != NULL; od = od->next) - if (od->common == vl->m && isSignal(od)) - { - if (noIntro) - { - setHasSigSlots(cd); - - prcode(fp, -"\n" -"static sipQtSignal signals_%C[] = {\n" - ,classFQCName(cd)); - - noIntro = FALSE; - } - - prcode(fp, -" {%N, %C_emit_%s},\n" - ,vl->m->pyname,classFQCName(cd),vl->m->pyname->text); - - break; - } - } - - if (!noIntro) - prcode(fp, -" {NULL, NULL}\n" -"};\n" - ); -} - - -/* - * Generate the protected enums for a class. - */ -static void generateProtectedEnums(sipSpec *pt,classDef *cd,FILE *fp) -{ - enumDef *ed; - - for (ed = pt->enums; ed != NULL; ed = ed->next) - { - char *eol; - enumMemberDef *emd; - - /* Ignore unless this class is the publisher. */ - if (cd != ed->pcd) - continue; - - prcode(fp, -"\n" -" /* Expose this protected enum. */\n" -" enum"); - - if (ed->fqcname != NULL) - prcode(fp," sip%s",scopedNameTail(ed->fqcname)); - - prcode(fp," {"); - - eol = "\n"; - - for (emd = ed->members; emd != NULL; emd = emd->next) - { - prcode(fp,"%s" -" %s = %S::%s",eol,emd->cname,classFQCName(ed->ecd),emd->cname); - - eol = ",\n"; - } - - prcode(fp,"\n" -" };\n" - ); - } -} - - -/* - * Generate the catcher for a virtual function. - */ -static void generateVirtualCatcher(sipSpec *pt, classDef *cd, int virtNr, - virtOverDef *vod, FILE *fp) -{ - overDef *od = &vod->o; - virtHandlerDef *vhd = od->virthandler; - argDef *res, *ad; - int a; - - normaliseArgs(od->cppsig); - - res = &od->cppsig->result; - - if (res->atype == void_type && res->nrderefs == 0) - res = NULL; - - prcode(fp, -"\n"); - - generateBaseType(&od->cppsig->result,fp); - - prcode(fp," sip%C::%O(",classFQCName(cd),od); - generateArgs(od->cppsig,Definition,fp); - prcode(fp,")%s%X\n" -"{\n" - ,(isConst(od) ? " const" : ""),od->exceptions); - - if (tracing) - { - prcode(fp, -" sipTrace(SIP_TRACE_CATCHERS,\""); - - generateBaseType(&od->cppsig->result,fp); - prcode(fp," sip%C::%O(",classFQCName(cd),od); - generateArgs(od->cppsig,Declaration,fp); - prcode(fp,")%s%X (this=0x%%08x)\\n\",this);\n" -"\n" - ,(isConst(od) ? " const" : ""),od->exceptions); - } - - restoreArgs(od->cppsig); - - if (vhd->module == pt->module) - { - prcode(fp, -" extern "); - - generateBaseType(&od->cppsig->result,fp); - - prcode(fp," sipVH_%s_%d(sip_gilstate_t,PyObject *",vhd->module->name,vhd->virthandlernr); - } - else - { - prcode(fp, -" typedef "); - - generateBaseType(&od->cppsig->result,fp); - - prcode(fp," (*sipVH_%s_%d)(sip_gilstate_t,PyObject *",vhd->module->name,vhd->virthandlernr); - } - - if (vhd->cppsig->nrArgs > 0) - { - prcode(fp,","); - generateArgs(vhd->cppsig,Declaration,fp); - } - - prcode(fp,");\n" - ); - - if (isNewThread(od)) - prcode(fp, -"\n" -" SIP_BLOCK_THREADS\n" - ); - - prcode(fp, -"\n" -" sip_gilstate_t sipGILState;\n" -" PyObject *meth;\n" -"\n" -" meth = sipIsPyMethod(&sipGILState,"); - - if (isConst(od)) - prcode(fp,"const_cast<sipMethodCache *>("); - - prcode(fp,"&sipPyMethods[%d]",virtNr); - - if (isConst(od)) - prcode(fp,")"); - - prcode(fp,",sipPySelf,"); - - if (isAbstract(od)) - prcode(fp,"%N",cd->iff->name); - else - prcode(fp,"NULL"); - - prcode(fp,",%N);\n" -"\n" - ,od->common->pyname); - - if (isNewThread(od)) - prcode(fp, -" if (meth)\n" -" {\n" -" sipStartThread();\n" -" "); - else - { - prcode(fp, -" if (!meth)\n" - ); - - if (isAbstract(od)) - generateVirtHandlerErrorReturn(res,fp); - else - { - if (res == NULL) - prcode(fp, -" {\n" -" "); - else - prcode(fp, -" return "); - - generateUnambiguousClass(cd,vod->scope,fp); - - prcode(fp,"::%O(",od); - - for (a = 0; a < od->cppsig->nrArgs; ++a) - prcode(fp,"%sa%d",(a == 0 ? "" : ","),a); - - prcode(fp,");\n" - ); - - if (res == NULL) - prcode(fp, -" return;\n" -" }\n" - ); - } - - prcode(fp, -"\n" -" "); - - if (res != NULL) - prcode(fp,"return "); - } - - if (vhd->module == pt->module) - prcode(fp,"sipVH_%s_%d",vhd->module->name,vhd->virthandlernr); - else - prcode(fp,"((sipVH_%s_%d)(sipModuleAPI_%s_%s->em_virthandlers[%d]))",vhd->module->name,vhd->virthandlernr,pt->module->name,vhd->module->name,vhd->virthandlernr); - - prcode(fp,"(sipGILState,meth"); - - ad = od->cppsig->args; - - for (a = 0; a < od->cppsig->nrArgs; ++a) - { - if (ad->atype == class_type && isProtectedClass(ad->u.cd)) - prcode(fp,",static_cast<%U *>(a%d)",ad->u.cd,a); - else if (ad->atype == enum_type && isProtectedEnum(ad->u.ed)) - prcode(fp, ",(%E)a%d", ad->u.ed, a); - else - prcode(fp,",a%d",a); - - ++ad; - } - - prcode(fp,");\n" - ); - - if (isNewThread(od)) - prcode(fp, -" sipEndThread();\n" -" }\n" -"\n" -" SIP_UNBLOCK_THREADS\n" - ); - - prcode(fp, -"}\n" - ); -} - - -/* - * Generate the scope of the near class of a virtual taking duplicate - * super-classes into account. - */ -static void generateUnambiguousClass(classDef *cd,classDef *scope,FILE *fp) -{ - mroDef *mro; - - /* See if the near class has a duplicate. */ - for (mro = cd->mro; mro != NULL; mro = mro->next) - if (mro->cd == scope) - { - if (hasDuplicateSuper(mro)) - { - mroDef *guardc; - - /* - * Backtrack to find the class that directly - * sub-classes the duplicated one. This will - * be the one that disambiguates the duplicated - * one. - */ - guardc = mro; - - while (guardc != cd->mro) - { - mroDef *sub; - classList *cl; - - for (sub = cd->mro; sub->next != guardc; sub = sub->next) - ; - - for (cl = sub->cd->supers; cl != NULL; cl = cl->next) - if (cl->cd == mro->cd) - { - prcode(fp,"%S",classFQCName(sub->cd)); - - return; - } - - /* Try the previous one. */ - guardc = sub; - } - } - - break; - } - - /* If we got here there is nothing to worry about. */ - prcode(fp,"%S",classFQCName(scope)); -} - - -/* - * Generate a cast to zero. - */ -static void generateCastZero(argDef *ad,FILE *fp) -{ - if (ad->atype == enum_type) - prcode(fp,"(%E)",ad->u.ed); - - prcode(fp,"0"); -} - - -/* - * Generate the return statement for a virtual handler when there has been an - * error (ie. there is nothing sensible to return). - */ -static void generateVirtHandlerErrorReturn(argDef *res,FILE *fp) -{ - prcode(fp, -" return"); - - if (res == NULL) - { - prcode(fp,";\n" - ); - - return; - } - - prcode(fp," "); - - if (res->atype == mapped_type && res->nrderefs == 0) - { - argDef res_noconstref; - - /* - * We don't know anything about the mapped type so we just hope - * is has a default ctor. - */ - - if (isReference(res)) - prcode(fp,"*new "); - - res_noconstref = *res; - resetIsConstArg(&res_noconstref); - resetIsReference(&res_noconstref); - prcode(fp,"%B()",&res_noconstref); - } - else if (res->atype == class_type && res->nrderefs == 0) - { - ctorDef *ct = res->u.cd->defctor; - - /* - * If we don't have a suitable ctor then the generated code - * will issue an error message. - */ - if (ct != NULL && isPublicCtor(ct) && ct->cppsig != NULL) - { - argDef res_noconstref; - - /* - * If this is a badly designed class. We can only - * generate correct code by leaking memory. - */ - if (isReference(res)) - prcode(fp,"*new "); - - res_noconstref = *res; - resetIsConstArg(&res_noconstref); - resetIsReference(&res_noconstref); - prcode(fp,"%B",&res_noconstref); - - generateCallDefaultCtor(ct,fp); - } - else - { - fatalScopedName(classFQCName(res->u.cd)); - fatal(" must have a default constructor\n"); - } - } - else - generateCastZero(res,fp); - - prcode(fp,";\n" - ); -} - - -/* - * Generate the call to a default ctor. - */ -static void generateCallDefaultCtor(ctorDef *ct, FILE *fp) -{ - int a; - - prcode(fp, "("); - - for (a = 0; a < ct->cppsig->nrArgs; ++a) - { - argDef *ad = &ct->cppsig->args[a]; - - if (ad->defval != NULL) - break; - - if (a > 0) - prcode(fp, ","); - - /* - * Do what we can to provide type information to the compiler. - */ - if (ad->atype == class_type && ad->nrderefs > 0 && !isReference(ad)) - prcode(fp, "static_cast<%B>(0)", ad); - else if (ad->atype == enum_type) - prcode(fp, "static_cast<%E>(0)", ad->u.ed); - else if (ad->atype == float_type || ad->atype == cfloat_type) - prcode(fp, "0.0F"); - else if (ad->atype == double_type || ad->atype == cdouble_type) - prcode(fp, "0.0"); - else if (ad->atype == uint_type) - prcode(fp, "0U"); - else if (ad->atype == long_type || ad->atype == longlong_type) - prcode(fp, "0L"); - else if (ad->atype == ulong_type || ad->atype == ulonglong_type) - prcode(fp, "0UL"); - else if ((ad->atype == ustring_type || ad->atype == sstring_type || ad->atype == string_type) && ad->nrderefs == 0) - prcode(fp, "'\\0'"); - else if (ad->atype == wstring_type && ad->nrderefs == 0) - prcode(fp, "L'\\0'"); - else - prcode(fp, "0"); - } - - prcode(fp, ")"); -} - - -/* - * Generate the emitter function for a signal. - */ -static void generateEmitter(sipSpec *pt,classDef *cd,visibleList *vl,FILE *fp) -{ - char *pname = vl->m->pyname->text; - overDef *od; - - prcode(fp, -"\n" -"int sip%C::sipEmit_%s(PyObject *sipArgs)\n" -"{\n" -" int sipArgsParsed = 0;\n" - ,classFQCName(cd),pname); - - for (od = vl->cd->overs; od != NULL; od = od->next) - { - int rgil = ((release_gil || isReleaseGIL(od)) && !isHoldGIL(od)); - - if (od->common != vl->m || !isSignal(od)) - continue; - - /* - * Generate the code that parses the args and emits the - * appropriate overloaded signal. - */ - prcode(fp, -"\n" -" {\n" - ); - - generateArgParser(pt, &od->pysig, cd, NULL, NULL, FALSE, fp); - - prcode(fp, -" {\n" - ); - - if (rgil) - prcode(fp, -" Py_BEGIN_ALLOW_THREADS\n" - ); - - prcode(fp, -" emit %s(" - ,od->cppname); - - generateArgs(od->cppsig,Call,fp); - - prcode(fp,");\n" - ); - - if (rgil) - prcode(fp, -" Py_END_ALLOW_THREADS\n" - ); - - deleteTemps(&od->pysig, fp); - - prcode(fp, -"\n" -" return 0;\n" -" }\n" -" }\n" - ); - } - - prcode(fp, -"\n" -" sipNoMethod(sipArgsParsed,%N,%N);\n" -"\n" -" return -1;\n" -"}\n" -"\n" - , cd->iff->name, vl->m->pyname); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static int %C_emit_%s(sipWrapper *, PyObject *);}\n" - , classFQCName(cd), pname); - - prcode(fp, -"static int %C_emit_%s(sipWrapper *w,PyObject *sipArgs)\n" -"{\n" -" sip%C *ptr = reinterpret_cast<sip%C *>(sipGetComplexCppPtr(w));\n" -"\n" -" return (ptr ? ptr->sipEmit_%s(sipArgs) : -1);\n" -"}\n" - ,classFQCName(cd),pname - ,classFQCName(cd),classFQCName(cd) - ,pname); -} - - -/* - * Generate the declarations of the protected wrapper functions for a class. - */ - -static void generateProtectedDeclarations(classDef *cd,FILE *fp) -{ - int noIntro; - visibleList *vl; - - noIntro = TRUE; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - overDef *od; - - if (vl->m->slot != no_slot) - continue; - - for (od = vl->cd->overs; od != NULL; od = od->next) - { - if (od->common != vl->m || !isProtected(od)) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -" /*\n" -" * There is a public method for every protected method visible from\n" -" * this class.\n" -" */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" "); - - if (isStatic(od)) - prcode(fp,"static "); - - generateBaseType(&od->cppsig->result,fp); - - if (!isStatic(od) && !isAbstract(od) && (isVirtual(od) || isVirtualReimp(od))) - { - prcode(fp, " sipProtectVirt_%s(bool", od->cppname); - - if (od->cppsig->nrArgs > 0) - prcode(fp, ","); - } - else - prcode(fp, " sipProtect_%s(", od->cppname); - - generateArgs(od->cppsig,Declaration,fp); - prcode(fp,")%s;\n" - ,(isConst(od) ? " const" : "")); - } - } -} - - -/* - * Generate the definitions of the protected wrapper functions for a class. - */ -static void generateProtectedDefinitions(classDef *cd,FILE *fp) -{ - visibleList *vl; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - overDef *od; - - if (vl->m->slot != no_slot) - continue; - - for (od = vl->cd->overs; od != NULL; od = od->next) - { - char *mname = od->cppname; - int parens; - argDef *res; - - if (od->common != vl->m || !isProtected(od)) - continue; - - prcode(fp, -"\n" - ); - - generateBaseType(&od->cppsig->result,fp); - - if (!isStatic(od) && !isAbstract(od) && (isVirtual(od) || isVirtualReimp(od))) - { - prcode(fp, " sip%C::sipProtectVirt_%s(bool sipSelfWasArg", classFQCName(cd), mname); - - if (od->cppsig->nrArgs > 0) - prcode(fp, ","); - } - else - prcode(fp, " sip%C::sipProtect_%s(", classFQCName(cd), mname); - - generateArgs(od->cppsig,Definition,fp); - prcode(fp,")%s\n" -"{\n" - ,(isConst(od) ? " const" : "")); - - parens = 1; - - res = &od->cppsig->result; - - if (res->atype == void_type && res->nrderefs == 0) - prcode(fp, -" "); - else - { - prcode(fp, -" return "); - - if (res->atype == class_type && isProtectedClass(res->u.cd)) - { - prcode(fp,"static_cast<%U *>(",res->u.cd); - ++parens; - } - else if (res->atype == enum_type && isProtectedEnum(res->u.ed)) - /* - * One or two older compilers can't - * handle a static_cast here so we - * revert to a C-style cast. - */ - prcode(fp,"(%E)",res->u.ed); - } - - if (!isAbstract(od)) - if (isVirtual(od) || isVirtualReimp(od)) - { - prcode(fp, "(sipSelfWasArg ? %S::%s(", classFQCName(vl->cd), mname); - - generateProtectedCallArgs(od, fp); - - prcode(fp, ") : "); - ++parens; - } - else - prcode(fp, "%S::", classFQCName(vl->cd)); - - prcode(fp,"%s(",mname); - - generateProtectedCallArgs(od, fp); - - while (parens--) - prcode(fp,")"); - - prcode(fp,";\n" -"}\n" - ); - } - } -} - - -/* - * Generate the arguments for a call to a protected method. - */ -static void generateProtectedCallArgs(overDef *od, FILE *fp) -{ - int a; - - for (a = 0; a < od->cppsig->nrArgs; ++a) - { - argDef *ad = &od->cppsig->args[a]; - - if (a > 0) - prcode(fp, ","); - - if (ad->atype == enum_type && isProtectedEnum(ad->u.ed)) - prcode(fp, "(%S)", ad->u.ed->fqcname); - - prcode(fp, "a%d", a); - } -} - - -/* - * Generate the function that does most of the work to handle a particular - * virtual function. - */ -static void generateVirtualHandler(sipSpec *pt,virtHandlerDef *vhd,FILE *fp) -{ - int a, nrvals, copy, isref; - argDef *res, res_noconstref; - - res = &vhd->cppsig->result; - - copy = isref = FALSE; - - if (res->atype == void_type && res->nrderefs == 0) - res = NULL; - else - { - /* - * If we are returning a reference to an instance then we take care to - * handle Python errors but still return a valid C++ instance. If we - * are returning an instance then we take care to make a local copy of - * the instance returned from Python before the Python object is - * garbage collected and the C++ instance (possibly) destroyed. - */ - if ((res->atype == class_type || res->atype == mapped_type) && res->nrderefs == 0) - if (isReference(res)) - isref = TRUE; - else - copy = TRUE; - - res_noconstref = *res; - resetIsConstArg(&res_noconstref); - resetIsReference(&res_noconstref); - } - - prcode(fp, -"\n" - ); - - generateBaseType(&vhd->cppsig->result, fp); - - prcode(fp," sipVH_%s_%d(sip_gilstate_t sipGILState,PyObject *sipMethod" - ,pt->module->name,vhd->virthandlernr); - - if (vhd->cppsig->nrArgs > 0) - { - prcode(fp,","); - - generateArgs(vhd->cppsig, Definition, fp); - } - - prcode(fp,")\n" -"{\n" - ); - - if (res != NULL) - { - prcode(fp, " "); - - /* - * wchar_t * return values are always on the heap. To reduce memory - * leaks we keep the last result around until we have a new one. This - * means that ownership of the return value stays with the function - * returning it - which is consistent with how other types work, even - * thought it may not be what's required in all cases. - */ - if (res->atype == wstring_type && res->nrderefs == 1) - prcode(fp, "static "); - - generateBaseType(&res_noconstref,fp); - - prcode(fp," %ssipRes",(isref ? "*" : "")); - - if (copy && res->atype == class_type && res->nrderefs == 0) - { - ctorDef *ct = res->u.cd->defctor; - - if (ct != NULL && isPublicCtor(ct) && ct->cppsig != NULL && ct->cppsig->nrArgs > 0 && ct->cppsig->args[0].defval == NULL) - generateCallDefaultCtor(ct,fp); - } - else if (!copy) - { - /* - * We initialise the result to try and suppress a - * compiler warning. - */ - prcode(fp," = "); - generateCastZero(res,fp); - } - - prcode(fp,";\n" - ); - - if (res->atype == wstring_type && res->nrderefs == 1) - prcode(fp, -"\n" -" if (sipRes)\n" -" {\n" -" // Return any previous result to the heap.\n" -" sipFree(%s);\n" -" sipRes = 0;\n" -" }\n" -"\n" - , (isConstArg(res) ? "const_cast<wchar_t *>(sipRes)" : "sipRes")); - } - - if (vhd->virtcode != NULL) - { - int error_flag = needErrorFlag(vhd->virtcode); - - if (error_flag) - prcode(fp, -" int sipIsErr = 0;\n" - ); - - prcode(fp, -"\n" - ); - - generateCppCodeBlock(vhd->virtcode,fp); - - if (error_flag) - prcode(fp, -"\n" -" if (sipIsErr)\n" -" PyErr_Print();\n" - ); - - prcode(fp, -"\n" -" Py_DECREF(sipMethod);\n" -"\n" -" SIP_RELEASE_GIL(sipGILState)\n" - ); - - if (res != NULL) - prcode(fp, -"\n" -" return sipRes;\n" - ); - - prcode(fp, -"}\n" - ); - - return; - } - - /* See how many values we expect. */ - nrvals = (res != NULL ? 1 : 0); - - for (a = 0; a < vhd->pysig->nrArgs; ++a) - if (isOutArg(&vhd->pysig->args[a])) - ++nrvals; - - if (copy) - { - prcode(fp, -" "); - - generateBaseType(&res_noconstref,fp); - - prcode(fp," *sipResOrig;\n"); - - if (res->atype == class_type && res->u.cd->convtocode != NULL) - prcode(fp, -" int sipResState;\n" - ); - } - - /* Call the method. */ - prcode(fp, -" PyObject *sipResObj = sipCallMethod(0,sipMethod,"); - - generateTupleBuilder(vhd->pysig, fp); - - prcode(fp,");\n" -"\n" -" %s (!sipResObj || sipParseResult(0,sipMethod,sipResObj,\"",(isref ? "int sipIsErr =" : "if")); - - /* Build the format string. */ - if (nrvals == 0) - prcode(fp,"Z"); - else - { - if (nrvals > 1) - prcode(fp,"("); - - if (res != NULL) - prcode(fp, "%s", getParseResultFormat(res, TRUE, isTransferVH(vhd))); - - for (a = 0; a < vhd->pysig->nrArgs; ++a) - { - argDef *ad = &vhd->pysig->args[a]; - - if (isOutArg(ad)) - prcode(fp, "%s", getParseResultFormat(ad, FALSE, FALSE)); - } - - if (nrvals > 1) - prcode(fp,")"); - } - - prcode(fp,"\""); - - /* Pass the destination pointers. */ - if (res != NULL) - { - generateParseResultExtraArgs(res, TRUE, fp); - prcode(fp,",&sipRes%s",(copy ? "Orig" : "")); - } - - for (a = 0; a < vhd->pysig->nrArgs; ++a) - { - argDef *ad = &vhd->pysig->args[a]; - - if (isOutArg(ad)) - { - generateParseResultExtraArgs(ad, FALSE, fp); - prcode(fp,",%sa%d",(isReference(ad) ? "&" : ""),a); - } - } - - if (isref) - prcode(fp,") < 0);\n" -"\n" -" if (sipIsErr)\n" - ); - else - prcode(fp,") < 0)\n" - ); - - prcode(fp, -" PyErr_Print();\n" - ); - - /* Make a copy if needed. */ - if (copy) - { - prcode(fp, -" else\n" -" {\n" -" sipRes = *sipResOrig;\n" - ); - - if (res->atype == mapped_type) - prcode(fp, -" delete sipResOrig;\n" - ); - else if (res->atype == class_type && res->u.cd->convtocode != NULL) - prcode(fp, -" sipReleaseInstance(sipResOrig,sipClass_%C,sipResState);\n" - , classFQCName(res->u.cd)); - - prcode(fp, -" }\n" - ); - } - - prcode(fp, -"\n" -" Py_XDECREF(sipResObj);\n" -" Py_DECREF(sipMethod);\n" -"\n" -" SIP_RELEASE_GIL(sipGILState)\n" - ); - - if (res != NULL) - { - if (isref) - { - prcode(fp, -"\n" -" if (sipIsErr)\n" - ); - - generateVirtHandlerErrorReturn(res,fp); - } - - prcode(fp, -"\n" -" return %ssipRes;\n" - ,(isref ? "*" : "")); - } - - prcode(fp, -"}\n" - ); -} - - -/* - * Generate the extra arguments needed by sipParseResult() for a particular - * type. - */ -static void generateParseResultExtraArgs(argDef *ad, int isres, FILE *fp) -{ - switch (ad->atype) - { - case mapped_type: - prcode(fp, ",sipMappedType_%T", ad); - break; - - case class_type: - prcode(fp, ",sipClass_%C", classFQCName(ad->u.cd)); - - if (isres && ad->nrderefs == 0 && ad->u.cd->convtocode != NULL && !isReference(ad)) - prcode(fp, ",&sipResState"); - - break; - - case pytuple_type: - prcode(fp,",&PyTuple_Type"); - break; - - case pylist_type: - prcode(fp,",&PyList_Type"); - break; - - case pydict_type: - prcode(fp,",&PyDict_Type"); - break; - - case pyslice_type: - prcode(fp,",&PySlice_Type"); - break; - - case pytype_type: - prcode(fp,",&PyType_Type"); - break; - - case enum_type: - if (ad->u.ed->fqcname != NULL) - prcode(fp,",sipEnum_%C",ad->u.ed->fqcname); - break; - } -} - - -/* - * Return the format characters used by sipParseResult() for a particular type. - */ -static const char *getParseResultFormat(argDef *ad, int isres, int xfervh) -{ - switch (ad->atype) - { - case mapped_type: - { - static const char *s[] = { - "D0", "D1", "D2", "D3", - "D4", "D5", "D6", "D7" - }; - - int f = 0x04; - - if (isres && ad->nrderefs == 0) - f |= 0x01; - - if (isres && xfervh) - f |= 0x02; - - return s[f]; - } - - case class_type: - { - static char s[] = "C?"; - - int f = 0x04; - - if (isres && ad->nrderefs == 0) - { - f |= 0x01; - - if (ad->u.cd->convtocode != NULL) - { - f &= ~0x04; - - /* - * If it is a reference then we are - * going to return the dereference. To - * make sure it remains valid we can - * either leak the temporary from the - * %ConvertToCode or we can suppress - * the %ConvertToCode. We choose the - * latter. - */ - if (isReference(ad)) - f |= 0x10; - } - } - - if (isres && xfervh) - f |= 0x02; - - s[1] = '0' + f; - - return s; - } - - case bool_type: - case cbool_type: - return "b"; - - case sstring_type: - case ustring_type: - case string_type: - return ((ad->nrderefs == 0) ? "c" : "s"); - - case wstring_type: - return ((ad->nrderefs == 0) ? "w" : "x"); - - case enum_type: - return ((ad->u.ed->fqcname != NULL) ? "E" : "e"); - - case ushort_type: - return "t"; - - case short_type: - return "h"; - - case int_type: - case cint_type: - return "i"; - - case uint_type: - return "u"; - - case long_type: - return "l"; - - case ulong_type: - return "m"; - - case longlong_type: - return "n"; - - case ulonglong_type: - return "o"; - - case void_type: - case struct_type: - return "V"; - - case float_type: - case cfloat_type: - return "f"; - - case double_type: - case cdouble_type: - return "d"; - - case pyobject_type: - return "O"; - - case pytuple_type: - case pylist_type: - case pydict_type: - case pyslice_type: - case pytype_type: - return (isAllowNone(ad) ? "N" : "T"); - } - - /* We should never get here. */ - return " "; -} - - -/* - * Generate the code to build a tuple of Python arguments. - */ -static void generateTupleBuilder(signatureDef *sd,FILE *fp) -{ - int a, arraylenarg; - - prcode(fp,"\""); - - for (a = 0; a < sd->nrArgs; ++a) - { - char *fmt = ""; - argDef *ad = &sd->args[a]; - - if (!isInArg(ad)) - continue; - - switch (ad->atype) - { - case sstring_type: - case ustring_type: - case string_type: - if (ad->nrderefs == 0 || (ad->nrderefs == 1 && isOutArg(ad))) - fmt = "c"; - else if (isArray(ad)) - fmt = "a"; - else - fmt = "s"; - - break; - - case wstring_type: - if (ad->nrderefs == 0 || (ad->nrderefs == 1 && isOutArg(ad))) - fmt = "w"; - else if (isArray(ad)) - fmt = "A"; - else - fmt = "x"; - - break; - - case bool_type: - case cbool_type: - fmt = "b"; - break; - - case enum_type: - fmt = (ad->u.ed->fqcname != NULL) ? "E" : "e"; - break; - - case cint_type: - fmt = "i"; - break; - - case uint_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "u"; - - break; - - case int_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "i"; - - break; - - case ushort_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "t"; - - break; - - case short_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "h"; - - break; - - case long_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "l"; - - break; - - case ulong_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "m"; - - break; - - case longlong_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "n"; - - break; - - case ulonglong_type: - if (isArraySize(ad)) - arraylenarg = a; - else - fmt = "o"; - - break; - - case struct_type: - case void_type: - fmt = "V"; - break; - - case float_type: - case cfloat_type: - fmt = "f"; - break; - - case double_type: - case cdouble_type: - fmt = "d"; - break; - - case signal_type: - case slot_type: - case slotcon_type: - case slotdis_type: - fmt = "s"; - break; - - case mapped_type: - fmt = "D"; - break; - - case class_type: - fmt = "C"; - break; - - case rxcon_type: - case rxdis_type: - case qobject_type: - fmt = "O"; - break; - - case pyobject_type: - case pytuple_type: - case pylist_type: - case pydict_type: - case pycallable_type: - case pyslice_type: - case pytype_type: - fmt = "S"; - break; - } - - prcode(fp,fmt); - } - - prcode(fp,"\""); - - for (a = 0; a < sd->nrArgs; ++a) - { - int derefs; - argDef *ad = &sd->args[a]; - - if (!isInArg(ad)) - continue; - - derefs = ad->nrderefs; - - switch (ad->atype) - { - case sstring_type: - case ustring_type: - case string_type: - case wstring_type: - if (!(ad->nrderefs == 0 || (ad->nrderefs == 1 && isOutArg(ad)))) - --derefs; - - break; - - case mapped_type: - case class_type: - if (ad->nrderefs > 0) - --derefs; - - break; - - case struct_type: - case void_type: - --derefs; - break; - } - - if (ad->atype == mapped_type || ad->atype == class_type || - ad->atype == rxcon_type || ad->atype == rxdis_type || - ad->atype == qobject_type) - { - prcode(fp,","); - - if (isConstArg(ad)) - prcode(fp,"const_cast<%b *>(",ad); - - if (ad->nrderefs == 0) - prcode(fp,"&"); - else - while (derefs-- != 0) - prcode(fp,"*"); - - prcode(fp,"a%d",a); - - if (isConstArg(ad)) - prcode(fp,")"); - - if (ad->atype == mapped_type) - prcode(fp, ",sipMappedType_%T,NULL", ad); - else if (ad->atype == class_type) - prcode(fp, ",sipClass_%C,NULL", classFQCName(ad->u.cd)); - else - prcode(fp,",sipClass_QObject"); - } - else - { - if (!isArraySize(ad)) - { - prcode(fp,","); - - while (derefs-- != 0) - prcode(fp,"*"); - - prcode(fp,"a%d",a); - } - - if (isArray(ad)) - { - argType astype = sd->args[arraylenarg].atype; - - prcode(fp,",%sa%d",(astype == int_type ? "" : "(int)"),arraylenarg); - } - else if (ad->atype == enum_type && ad->u.ed->fqcname != NULL) - prcode(fp,",sipEnum_%C",ad->u.ed->fqcname); - } - } -} - - -/* - * Generate the class interface #include directives required by either a class - * or a module. - */ -static void generateUsedIncludes(ifaceFileList *iffl, int header, FILE *fp) -{ - int newl = TRUE; - - while (iffl != NULL) - { - if (header == iffl->header) - { - if (newl) - { - prcode(fp, -"\n" - ); - - newl = FALSE; - } - - prcode(fp, -"#include \"sip%s%F.h\"\n" - , iffl->iff->module->name, iffl->iff->fqcname); - } - - iffl = iffl->next; - } - - if (!newl) - prcode(fp, -"\n" - ); -} - - -/* - * Generate the header file for the C++ interface. - */ -static void generateIfaceHeader(sipSpec *pt,ifaceFileDef *iff,char *codeDir) -{ - char *wfile; - char *cmname = iff->module->name; - classDef *cd; - mappedTypeDef *mtd; - exceptionDef *xd; - int genused; - FILE *fp; - - /* Create the header file. */ - - wfile = createIfaceFileName(codeDir,iff,".h"); - fp = createFile(pt,wfile,"Interface header file."); - - prcode(fp, -"\n" -"#ifndef _%s%F_h\n" -"#define _%s%F_h\n" -"\n" - ,cmname,iff->fqcname,cmname,iff->fqcname); - - genused = TRUE; - - for (cd = pt->classes; cd != NULL; cd = cd->next) - if (cd->iff == iff) - { - if (iff->module == pt->module) - generateClassHeader(cd,genused,pt,fp); - else if (!isExternal(cd)) - generateImportedClassHeader(cd,pt,fp); - - genused = FALSE; - } - - genused = TRUE; - - for (mtd = pt->mappedtypes; mtd != NULL; mtd = mtd->next) - if (mtd->iff == iff) - { - if (iff->module == pt->module) - generateMappedTypeHeader(mtd,genused,fp); - else - generateImportedMappedTypeHeader(mtd,pt,fp); - - genused = FALSE; - } - - for (xd = pt->exceptions; xd != NULL; xd = xd->next) - if (xd->iff == iff) - { - generateCppCodeBlock(xd->hdrcode,fp); - - if (xd->exceptionnr >= 0) - { - prcode(fp, -"\n" -"#define sipException_%C sipModuleAPI_%s" - ,iff->fqcname,pt->module->name); - - if (iff->module == pt->module) - prcode(fp,"."); - else - prcode(fp,"_%s->",iff->module->name); - - prcode(fp,"em_exceptions[%d]\n" - ,xd->exceptionnr); - } - } - - prcode(fp, -"\n" -"#endif\n" - ); - - closeFile(fp); - free(wfile); -} - - -/* - * Generate the C++ header code for an imported mapped type. - */ -static void generateImportedMappedTypeHeader(mappedTypeDef *mtd,sipSpec *pt, - FILE *fp) -{ - char *mname = pt->module->name; - char *imname = mtd->iff->module->name; - argDef type; - - generateCppCodeBlock(mtd->hdrcode,fp); - - type.atype = mapped_type; - type.u.mtd = mtd; - type.argflags = 0; - type.name = NULL; - type.nrderefs = 0; - type.defval = NULL; - - prcode(fp, -"\n" -"#define sipMappedType_%T sipModuleAPI_%s_%s->em_mappedtypes[%d]\n" -"#define sipForceConvertTo_%T sipModuleAPI_%s_%s->em_mappedtypes[%d]->mt_fcto\n" -"#define sipConvertFrom_%T sipModuleAPI_%s_%s->em_mappedtypes[%d]->mt_cfrom\n" - ,&type,mname,imname,mtd->mappednr - ,&type,mname,imname,mtd->mappednr - ,&type,mname,imname,mtd->mappednr); -} - - -/* - * Generate the C++ header code for a generated mapped type. - */ -static void generateMappedTypeHeader(mappedTypeDef *mtd,int genused,FILE *fp) -{ - prcode(fp, -"\n" -"\n" - ); - - generateCppCodeBlock(mtd->hdrcode,fp); - - if (genused) - generateUsedIncludes(mtd->iff->used, TRUE, fp); - - prcode(fp, -"\n" -"#define sipMappedType_%T &sipMappedTypeDef_%T\n" -"#define sipForceConvertTo_%T sipMappedTypeDef_%T.mt_fcto\n" -"#define sipConvertFrom_%T sipMappedTypeDef_%T.mt_cfrom\n" -"\n" -"extern sipMappedType sipMappedTypeDef_%T;\n" - ,&mtd->type,&mtd->type - ,&mtd->type,&mtd->type - ,&mtd->type,&mtd->type - ,&mtd->type); -} - - -/* - * Generate the C++ header code for an imported class. - */ -static void generateImportedClassHeader(classDef *cd,sipSpec *pt,FILE *fp) -{ - char *mname = pt->module->name; - char *imname = cd->iff->module->name; - classDef *hcd; - - for (hcd = cd; hcd != NULL; hcd = hcd->ecd) - generateCppCodeBlock(hcd->hdrcode,fp); - - prcode(fp, -"\n" -"#define sipClass_%C sipModuleAPI_%s_%s->em_types[%d]\n" -"#define sipCast_%C sipModuleAPI_%s_%s->em_types[%d]->type->td_cast\n" -"#define sipForceConvertTo_%C sipModuleAPI_%s_%s->em_types[%d]->type->td_fcto\n" - ,classFQCName(cd),mname,imname,cd->classnr - ,classFQCName(cd),mname,imname,cd->classnr - ,classFQCName(cd),mname,imname,cd->classnr); - - generateEnumMacros(pt, cd, fp); -} - - -/* - * Generate the C++ header code for a generated class. - */ -static void generateClassHeader(classDef *cd,int genused,sipSpec *pt,FILE *fp) -{ - char *mname = pt->module->name; - classDef *hcd; - - for (hcd = cd; hcd != NULL; hcd = hcd->ecd) - generateCppCodeBlock(hcd->hdrcode,fp); - - if (genused) - generateUsedIncludes(cd->iff->used, TRUE, fp); - - if (cd->iff->type != namespace_iface) - { - prcode(fp, -"\n" -"#define sipClass_%C sipModuleAPI_%s.em_types[%d]\n" - ,classFQCName(cd),mname,cd->classnr); - - if (!isExternal(cd)) - prcode(fp, -"#define sipCast_%C sipType_%s_%C.td_cast\n" -"#define sipForceConvertTo_%C sipType_%s_%C.td_fcto\n" - , classFQCName(cd), mname, classFQCName(cd) - , classFQCName(cd), mname, classFQCName(cd)); - } - - generateEnumMacros(pt, cd, fp); - - if (!isExternal(cd)) - prcode(fp, -"\n" -"extern sipTypeDef sipType_%s_%C;\n" - , mname, classFQCName(cd)); - - if (hasShadow(cd)) - generateShadowClassDeclaration(pt,cd,fp); -} - - -/* - * Generate the sipEnum_* macros. - */ -static void generateEnumMacros(sipSpec *pt, classDef *cd, FILE *fp) -{ - enumDef *ed; - int noIntro = TRUE; - - for (ed = pt->enums; ed != NULL; ed = ed->next) - { - if (ed->fqcname == NULL || ed->ecd != cd) - continue; - - if (noIntro) - { - prcode(fp, -"\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -"#define sipEnum_%C sipModuleAPI_%s", ed->fqcname, pt->module->name); - - if (pt->module == ed->module) - prcode(fp, "."); - else - prcode(fp, "_%s->", ed->module->name); - - prcode(fp, "em_enums[%d]\n" - , ed->enumnr); - } -} - - -/* - * Generate the shadow class declaration. - */ -static void generateShadowClassDeclaration(sipSpec *pt,classDef *cd,FILE *fp) -{ - int noIntro, nrVirts; - ctorDef *ct; - virtOverDef *vod; - classDef *pcd; - - prcode(fp, -"\n" -"\n" -"class sip%C : public %S\n" -"{\n" -"public:\n" - ,classFQCName(cd),classFQCName(cd)); - - /* Define a shadow class for any protected classes we have. */ - - for (pcd = pt->classes; pcd != NULL; pcd = pcd->next) - { - if (pcd->ecd != cd || !isProtectedClass(pcd)) - continue; - - prcode(fp, -" class sip%s : public %s {};\n" - ,classBaseName(pcd),classBaseName(pcd)); - } - - /* The constructor declarations. */ - - for (ct = cd->ctors; ct != NULL; ct = ct->next) - { - ctorDef *dct; - - if (isPrivateCtor(ct)) - continue; - - if (ct->cppsig == NULL) - continue; - - /* Check we haven't already handled this C++ signature. */ - for (dct = cd->ctors; dct != ct; dct = dct->next) - if (dct->cppsig != NULL && sameSignature(dct->cppsig, ct->cppsig, TRUE)) - break; - - if (dct != ct) - continue; - - prcode(fp, -" sip%C(",classFQCName(cd)); - - generateArgs(ct->cppsig,Declaration,fp); - - prcode(fp,")%X;\n" - ,ct->exceptions); - } - - /* The destructor. */ - - if (!isPrivateDtor(cd)) - prcode(fp, -" %s~sip%C()%X;\n" - ,(cd->vmembers != NULL ? "virtual " : ""),classFQCName(cd),cd->dtorexceptions); - - /* The metacall methods if required. */ - if (isQObjectSubClass(cd) && optQ_OBJECT4(pt)) - prcode(fp, -"\n" -" const TQMetaObject *metaObject() const;\n" -" int qt_metacall(TQMetaObject::Call,int,void **);\n" - ); - - /* The exposure of protected enums. */ - - generateProtectedEnums(pt,cd,fp); - - /* The wrapper around each protected member function. */ - - generateProtectedDeclarations(cd,fp); - - /* The public wrapper around each signal emitter. */ - if (!optNoEmitters(pt)) - { - visibleList *vl; - - noIntro = TRUE; - - for (vl = cd->visible; vl != NULL; vl = vl->next) - { - overDef *od; - - if (vl->m->slot != no_slot) - continue; - - for (od = vl->cd->overs; od != NULL; od = od->next) - { - if (od->common != vl->m || !isSignal(od)) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -" /*\n" -" * There is a public method for every Qt signal that can be emitted\n" -" * by this object. This function is called by Python to emit the\n" -" * signal.\n" -" */\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" int sipEmit_%s(PyObject *);\n" - ,vl->m->pyname->text); - - break; - } - } - } - - /* The catcher around each virtual function in the hierarchy. */ - noIntro = TRUE; - - for (vod = cd->vmembers; vod != NULL; vod = vod->next) - { - overDef *od = &vod->o; - virtOverDef *dvod; - - if (isPrivate(od)) - continue; - - /* Check we haven't already handled this C++ signature. */ - for (dvod = cd->vmembers; dvod != vod; dvod = dvod->next) - if (strcmp(dvod->o.cppname,od->cppname) == 0 && sameSignature(dvod->o.cppsig,od->cppsig,TRUE)) - break; - - if (dvod != vod) - continue; - - if (noIntro) - { - prcode(fp, -"\n" -" /*\n" -" * There is a protected method for every virtual method visible from\n" -" * this class.\n" -" */\n" -"protected:\n" - ); - - noIntro = FALSE; - } - - prcode(fp, -" "); - - prOverloadDecl(fp, od, FALSE); - prcode(fp, ";\n"); - } - - prcode(fp, -"\n" -"public:\n" -" sipWrapper *sipPySelf;\n" - ); - - /* The private declarations. */ - - prcode(fp, -"\n" -"private:\n" -" sip%C(const sip%C &);\n" -" sip%C &operator = (const sip%C &);\n" - ,classFQCName(cd),classFQCName(cd) - ,classFQCName(cd),classFQCName(cd)); - - if ((nrVirts = countVirtuals(cd)) > 0) - prcode(fp, -"\n" -" sipMethodCache sipPyMethods[%d];\n" - ,nrVirts); - - prcode(fp, -"};\n" - ); -} - - -/* - * Generate the C++ declaration for an overload. - */ -void prOverloadDecl(FILE *fp, overDef *od, int defval) -{ - int a; - - normaliseArgs(od->cppsig); - - generateBaseType(&od->cppsig->result, fp); - - prcode(fp, " %O(", od); - - for (a = 0; a < od->cppsig->nrArgs; ++a) - { - argDef *ad = &od->cppsig->args[a]; - - if (a > 0) - prcode(fp, ","); - - generateBaseType(ad, fp); - - if (defval && ad->defval != NULL) - { - prcode(fp, " = "); - generateExpression(ad->defval, fp); - } - } - - prcode(fp, ")%s%X", (isConst(od) ? " const" : ""), od->exceptions); - - restoreArgs(od->cppsig); -} - - -/* - * Generate typed arguments. - */ -static void generateArgs(signatureDef *sd,funcArgType ftype,FILE *fp) -{ - int a; - - for (a = 0; a < sd->nrArgs; ++a) - { - if (a > 0) - prcode(fp,","); - - generateSingleArg(&sd->args[a],a,ftype,fp); - } -} - - -/* - * Generate the declaration of a named variable to hold a result from a C++ - * function call. - */ -static void generateNamedValueType(argDef *ad,char *name,FILE *fp) -{ - argDef mod = *ad; - - if (ad->nrderefs == 0) - if (ad->atype == class_type || ad->atype == mapped_type) - mod.nrderefs = 1; - else - resetIsConstArg(&mod); - - resetIsReference(&mod); - generateNamedBaseType(&mod,name,fp); -} - - -/* - * Generate a single argument. - */ -static void generateSingleArg(argDef *ad,int argnr,funcArgType ftype,FILE *fp) -{ - char name[50]; - int genType, genName, derefPtr; - - /* Break the type down to individual modifications. */ - - genType = FALSE; - genName = FALSE; - derefPtr = FALSE; - - switch (ftype) - { - case Call: - genName = TRUE; - derefPtr = TRUE; - break; - - case Declaration: - genType = TRUE; - break; - - case Definition: - genType = TRUE; - genName = TRUE; - break; - } - - if (genName) - { - char *ind = ""; - - if (derefPtr) - switch (ad->atype) - { - case sstring_type: - case ustring_type: - case string_type: - case wstring_type: - if (ad->nrderefs > (isOutArg(ad) ? 0 : 1)) - ind = "&"; - - break; - - case mapped_type: - case class_type: - if (ad->nrderefs == 2) - ind = "&"; - else if (ad->nrderefs == 0) - ind = "*"; - - break; - - case struct_type: - case void_type: - if (ad->nrderefs == 2) - ind = "&"; - - break; - - default: - if (ad->nrderefs == 1) - ind = "&"; - } - - sprintf(name,"%sa%d",ind,argnr); - } - else - name[0] = '\0'; - - if (genType) - generateNamedBaseType(ad,name,fp); - else if (genName) - prcode(fp,name); -} - - -/* - * Generate a C++ type. - */ -static void generateBaseType(argDef *ad,FILE *fp) -{ - generateNamedBaseType(ad,"",fp); -} - - -/* - * Generate a C++ type and name. - */ -static void generateNamedBaseType(argDef *ad,char *name,FILE *fp) -{ - int nr_derefs = ad->nrderefs; - - /* - * A function type is handled differently because of the position of - * the name. - */ - if (ad->atype == function_type) - { - int i; - signatureDef *sig = ad->u.sa; - - generateBaseType(&sig->result,fp); - - prcode(fp," ("); - - for (i = 0; i < nr_derefs; ++i) - prcode(fp,"*"); - - prcode(fp,"%s)(",name); - generateArgs(sig,Declaration,fp); - prcode(fp,")"); - - return; - } - - if (isConstArg(ad)) - prcode(fp,"const "); - - switch (ad->atype) - { - case sstring_type: - prcode(fp,"signed char"); - break; - - case ustring_type: - prcode(fp,"unsigned char"); - break; - - case wstring_type: - prcode(fp,"wchar_t"); - break; - - case signal_type: - case slot_type: - case anyslot_type: - case slotcon_type: - case slotdis_type: - nr_derefs = 1; - - /* Drop through. */ - - case string_type: - prcode(fp,"char"); - break; - - case ushort_type: - prcode(fp,"unsigned short"); - break; - - case short_type: - prcode(fp,"short"); - break; - - case uint_type: - prcode(fp,"unsigned"); - break; - - case int_type: - case cint_type: - prcode(fp,"int"); - break; - - case ulong_type: - prcode(fp,"unsigned long"); - break; - - case long_type: - prcode(fp,"long"); - break; - - case ulonglong_type: - prcode(fp,"unsigned PY_LONG_LONG"); - break; - - case longlong_type: - prcode(fp,"PY_LONG_LONG"); - break; - - case struct_type: - prcode(fp,"struct %S",ad->u.sname); - break; - - case void_type: - prcode(fp,"void"); - break; - - case bool_type: - case cbool_type: - prcode(fp,"bool"); - break; - - case float_type: - case cfloat_type: - prcode(fp,"float"); - break; - - case double_type: - case cdouble_type: - prcode(fp,"double"); - break; - - case defined_type: - /* - * The only defined types still remaining are arguments to - * templates. - */ - - prcode(fp,"%S",ad->u.snd); - break; - - case rxcon_type: - case rxdis_type: - nr_derefs = 1; - prcode(fp,"TQObject"); - break; - - case mapped_type: - generateBaseType(&ad->u.mtd->type,fp); - break; - - case class_type: - prcode(fp,"%U",ad->u.cd); - break; - - case template_type: - { - static const char tail[] = ">"; - int a; - templateDef *td = ad->u.td; - - prcode(fp, "%S%s", td->fqname, (prcode_xml ? "<" : "<")); - - for (a = 0; a < td->types.nrArgs; ++a) - { - if (a > 0) - prcode(fp,","); - - generateBaseType(&td->types.args[a],fp); - } - - if (prcode_last == tail) - prcode(fp, " "); - - prcode(fp, (prcode_xml ? ">" : tail)); - break; - } - - case enum_type: - prcode(fp,"%E",ad->u.ed); - break; - - case pyobject_type: - case pytuple_type: - case pylist_type: - case pydict_type: - case pycallable_type: - case pyslice_type: - case pytype_type: - case qobject_type: - case ellipsis_type: - prcode(fp, "PyObject *"); - break; - } - - if (nr_derefs > 0) - { - int i; - - prcode(fp," "); - - for (i = 0; i < nr_derefs; ++i) - prcode(fp,"*"); - } - - if (isReference(ad)) - prcode(fp, (prcode_xml ? "&" : "&")); - - if (*name != '\0') - { - if (nr_derefs == 0) - prcode(fp," "); - - prcode(fp,name); - } -} - - -/* - * Generate the definition of an argument variable and any supporting - * variables. - */ -static void generateVariable(argDef *ad,int argnr,FILE *fp) -{ - argType atype = ad->atype; - argDef orig; - - if (isInArg(ad) && ad->defval != NULL && - (atype == class_type || atype == mapped_type) && - (ad->nrderefs == 0 || isReference(ad))) - { - /* - * Generate something to hold the default value as it cannot be - * assigned straight away. - */ - prcode(fp, -" %B a%ddef = ",ad,argnr); - - generateExpression(ad->defval,fp); - - prcode(fp,";\n" - ); - } - - /* Adjust the type so we have the type that will really handle it. */ - - orig = *ad; - - switch (atype) - { - case sstring_type: - case ustring_type: - case string_type: - case wstring_type: - if (!isReference(ad)) - if (ad->nrderefs == 2) - ad->nrderefs = 1; - else if (ad->nrderefs == 1 && isOutArg(ad)) - ad->nrderefs = 0; - - break; - - case mapped_type: - case class_type: - case void_type: - case struct_type: - ad->nrderefs = 1; - break; - - default: - ad->nrderefs = 0; - } - - /* Array sizes are always integers. */ - if (isArraySize(ad)) - ad->atype = int_type; - - resetIsReference(ad); - - if (ad->nrderefs == 0) - resetIsConstArg(ad); - - prcode(fp, -" %B a%d",ad,argnr); - - if (atype == anyslot_type) - prcode(fp, "Name"); - - *ad = orig; - - generateDefaultValue(ad, argnr, fp); - - prcode(fp,";\n" - ); - - /* Some types have supporting variables. */ - if (isInArg(ad)) - switch (atype) - { - case class_type: - if (ad->u.cd->convtocode != NULL && !isConstrained(ad)) - prcode(fp, -" int a%dState = 0;\n" - ,argnr); - - if (isGetWrapper(ad)) - prcode(fp, -" PyObject *a%dWrapper;\n" - ,argnr); - - break; - - case mapped_type: - prcode(fp, -" int a%dState = 0;\n" - ,argnr); - break; - - case anyslot_type: - prcode(fp, -" PyObject *a%dCallable", argnr); - generateDefaultValue(ad, argnr, fp); - prcode(fp, ";\n" - ); - break; - } -} - - -/* - * Generate a default value. - */ -static void generateDefaultValue(argDef *ad, int argnr, FILE *fp) -{ - if (isInArg(ad) && ad->defval != NULL) - { - prcode(fp," = "); - - if ((ad->atype == class_type || ad->atype == mapped_type) && - (ad->nrderefs == 0 || isReference(ad))) - prcode(fp, "&a%ddef", argnr); - else - generateExpression(ad->defval,fp); - } -} - - -/* - * Generate a simple function call. - */ -static void generateSimpleFunctionCall(fcallDef *fcd,FILE *fp) -{ - int i; - - prcode(fp, "%B(", &fcd->type); - - for (i = 0; i < fcd->nrArgs; ++i) - { - if (i > 0) - prcode(fp,","); - - generateExpression(fcd->args[i],fp); - } - - prcode(fp,")"); -} - - -/* - * Generate the type structure that contains all the information needed by the - * metatype. A sub-set of this is used to extend namespaces. - */ -static void generateTypeDefinition(sipSpec *pt, classDef *cd, FILE *fp) -{ - char *mname = pt->module->name; - const char *sep; - int is_slots, nr_methods, nr_enums; - 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, is_inst_enum; - memberDef *md; - - if (cd->supers != NULL) - { - classList *cl; - - prcode(fp, -"\n" -"\n" -"/* Define this type's super-types. */\n" -"static sipEncodedClassDef supers_%C[] = {",classFQCName(cd)); - - for (cl = cd->supers; cl != NULL; cl = cl->next) - { - if (cl != cd->supers) - prcode(fp,", "); - - generateEncodedClass(pt,cl->cd,(cl->next == NULL),fp); - } - - prcode(fp,"};\n" - ); - } - - /* Generate the slots table. */ - is_slots = FALSE; - - for (md = cd->members; md != NULL; md = md->next) - { - const char *stype; - - if (md->slot == no_slot) - continue; - - if (!is_slots) - { - prcode(fp, -"\n" -"\n" -"/* Define this type's Python slots. */\n" -"static sipPySlotDef slots_%C[] = {\n" - ,classFQCName(cd)); - - is_slots = TRUE; - } - - if ((stype = slotName(md->slot)) != NULL) - prcode(fp, -" {(void *)slot_%C_%s, %s},\n" - ,classFQCName(cd),md->pyname->text,stype); - } - - if (is_slots) - prcode(fp, -" {0, (sipPySlotType)0}\n" -"};\n" - ); - - /* Generate the attributes tables. */ - nr_methods = generateMethodTable(cd,fp); - nr_enums = generateEnumMemberTable(pt,cd,fp); - - /* Generate each instance table. */ - is_inst_class = generateClasses(pt,cd,fp); - is_inst_voidp = generateVoidPointers(pt,cd,fp); - is_inst_char = generateChars(pt,cd,fp); - is_inst_string = generateStrings(pt,cd,fp); - is_inst_int = generateInts(pt,cd,fp); - is_inst_long = generateLongs(pt,cd,fp); - is_inst_ulong = generateUnsignedLongs(pt,cd,fp); - is_inst_longlong = generateLongLongs(pt,cd,fp); - is_inst_ulonglong = generateUnsignedLongLongs(pt,cd,fp); - is_inst_double = generateDoubles(pt,cd,fp); - is_inst_enum = generateEnums(pt,cd,fp); - - prcode(fp, -"\n" -"\n" -"sipTypeDef sipType_%s_%C = {\n" -" 0,\n" -" ", mname, classFQCName(cd)); - - sep = ""; - - if (cd->userflags) - { - prcode(fp, "%s%x", sep, ((cd->userflags << TYPE_FLAGS_SHIFT) & TYPE_FLAGS_MASK)); - sep = "|"; - } - - if (isAbstractClass(cd)) - { - prcode(fp, "%sSIP_TYPE_ABSTRACT", sep); - sep = "|"; - } - - if (cd->subbase != NULL) - { - prcode(fp, "%sSIP_TYPE_SCC", sep); - sep = "|"; - } - - if (*sep == '\0') - prcode(fp, "0"); - - prcode(fp, ",\n"); - - if (cd->real != NULL) - prcode(fp, -" 0,\n" - ); - else if (cd->ecd != NULL && cd->ecd->real != NULL) - prcode(fp, -" \"%s.%P\",\n" - , cd->ecd->real->iff->module->name, cd->ecd, cd->pyname); - else - prcode(fp, -" \"%s.%P\",\n" - , mname, cd->ecd, cd->pyname); - - if (isRenamedClass(cd)) - prcode(fp, -" \"%S\",\n" - , classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - prcode(fp, -" "); - - if (cd->real != NULL) - generateEncodedClass(pt, cd->real, 0, fp); - else if (cd->ecd != NULL) - generateEncodedClass(pt, cd->ecd, 0, fp); - else - prcode(fp, "{0, 0, 1}"); - - prcode(fp, ",\n" - ); - - if (cd->supers != NULL) - prcode(fp, -" supers_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (is_slots) - prcode(fp, -" slots_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (nr_methods == 0) - prcode(fp, -" 0, 0,\n" - ); - else - prcode(fp, -" %d, methods_%C,\n" - ,nr_methods,classFQCName(cd)); - - if (nr_enums == 0) - prcode(fp, -" 0, 0,\n" - ); - else - prcode(fp, -" %d, enummembers_%C,\n" - ,nr_enums,classFQCName(cd)); - - if (hasVarHandlers(cd)) - prcode(fp, -" variables_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (canCreate(cd)) - prcode(fp, -" init_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->travcode != NULL) - prcode(fp, -" traverse_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->clearcode != NULL) - prcode(fp, -" clear_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->readbufcode != NULL) - prcode(fp, -" getreadbuffer_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->writebufcode != NULL) - prcode(fp, -" getwritebuffer_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->segcountcode != NULL) - prcode(fp, -" getsegcount_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->charbufcode != NULL) - prcode(fp, -" getcharbuffer_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (needDealloc(cd)) - prcode(fp, -" dealloc_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - if (cd->iff->type == namespace_iface || generating_c) - prcode(fp, -" 0,\n" -" 0,\n" - ); - else - prcode(fp, -" cast_%C,\n" -" release_%C,\n" - , classFQCName(cd) - , classFQCName(cd)); - - if (cd->iff->type == namespace_iface) - prcode(fp, -" 0,\n" -" 0,\n" - ); - else - { - prcode(fp, -" forceConvertTo_%C,\n" - ,classFQCName(cd)); - - if (cd->convtocode != NULL) - prcode(fp, -" convertTo_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - } - - if (!optNoEmitters(pt) && hasSigSlots(cd)) - prcode(fp, -" signals_%C,\n" - ,classFQCName(cd)); - else - prcode(fp, -" 0,\n" - ); - - prcode(fp, -" {"); - - if (is_inst_class) - prcode(fp,"classInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_voidp) - prcode(fp,"voidPtrInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_char) - prcode(fp,"charInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_string) - prcode(fp,"stringInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_int) - prcode(fp,"intInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_long) - prcode(fp,"longInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_ulong) - prcode(fp,"unsignedLongInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_longlong) - prcode(fp,"longLongInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_ulonglong) - prcode(fp,"unsignedLongLongInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_double) - prcode(fp,"doubleInstances_%C, ",classFQCName(cd)); - else - prcode(fp,"0, "); - - if (is_inst_enum) - prcode(fp,"enumInstances_%C",classFQCName(cd)); - else - prcode(fp,"0"); - - prcode(fp,"},\n" -" 0\n" -"};\n" - ); -} - - -/* - * Return the sip module's string equivalent of a slot. - */ -static const char *slotName(slotType st) -{ - const char *sn; - - switch (st) - { - case str_slot: - sn = "str_slot"; - break; - - case int_slot: - sn = "int_slot"; - break; - - case long_slot: - sn = "long_slot"; - break; - - case float_slot: - sn = "float_slot"; - break; - - case len_slot: - sn = "len_slot"; - break; - - case contains_slot: - sn = "contains_slot"; - break; - - case add_slot: - sn = "add_slot"; - break; - - case concat_slot: - sn = "concat_slot"; - break; - - case sub_slot: - sn = "sub_slot"; - break; - - case mul_slot: - sn = "mul_slot"; - break; - - case repeat_slot: - sn = "repeat_slot"; - break; - - case div_slot: - sn = "div_slot"; - break; - - case mod_slot: - sn = "mod_slot"; - break; - - case and_slot: - sn = "and_slot"; - break; - - case or_slot: - sn = "or_slot"; - break; - - case xor_slot: - sn = "xor_slot"; - break; - - case lshift_slot: - sn = "lshift_slot"; - break; - - case rshift_slot: - sn = "rshift_slot"; - break; - - case iadd_slot: - sn = "iadd_slot"; - break; - - case iconcat_slot: - sn = "iconcat_slot"; - break; - - case isub_slot: - sn = "isub_slot"; - break; - - case imul_slot: - sn = "imul_slot"; - break; - - case irepeat_slot: - sn = "irepeat_slot"; - break; - - case idiv_slot: - sn = "idiv_slot"; - break; - - case imod_slot: - sn = "imod_slot"; - break; - - case iand_slot: - sn = "iand_slot"; - break; - - case ior_slot: - sn = "ior_slot"; - break; - - case ixor_slot: - sn = "ixor_slot"; - break; - - case ilshift_slot: - sn = "ilshift_slot"; - break; - - case irshift_slot: - sn = "irshift_slot"; - break; - - case invert_slot: - sn = "invert_slot"; - break; - - case call_slot: - sn = "call_slot"; - break; - - case getitem_slot: - sn = "getitem_slot"; - break; - - case setitem_slot: - sn = "setitem_slot"; - break; - - case delitem_slot: - sn = "delitem_slot"; - break; - - case lt_slot: - sn = "lt_slot"; - break; - - case le_slot: - sn = "le_slot"; - break; - - case eq_slot: - sn = "eq_slot"; - break; - - case ne_slot: - sn = "ne_slot"; - break; - - case gt_slot: - sn = "gt_slot"; - break; - - case ge_slot: - sn = "ge_slot"; - break; - - case cmp_slot: - sn = "cmp_slot"; - break; - - case nonzero_slot: - sn = "nonzero_slot"; - break; - - case neg_slot: - sn = "neg_slot"; - break; - - case pos_slot: - sn = "pos_slot"; - break; - - case abs_slot: - sn = "abs_slot"; - break; - - case repr_slot: - sn = "repr_slot"; - break; - - case hash_slot: - sn = "hash_slot"; - break; - - default: - sn = NULL; - } - - return sn; -} - - -/* - * Generate the code to register a class as a Qt metatype. - */ -static void generateRegisterMetaType(classDef *cd, FILE *fp) -{ - int pub_def_ctor, pub_copy_ctor; - ctorDef *ct; - - /* - * We register types with Qt if the class is not abstract, has a public - * default ctor, a public copy ctor, a public dtor and isn't one of the - * internally supported types. - */ - if (isAbstractClass(cd)) - return; - - if (!isPublicDtor(cd)) - return; - - if (classFQCName(cd)->next == NULL) - { - if (strcmp(classBaseName(cd), "TQChar") == 0) - return; - - if (strcmp(classBaseName(cd), "TQString") == 0) - return; - - if (strcmp(classBaseName(cd), "TQByteArray") == 0) - return; - } - - pub_def_ctor = pub_copy_ctor = FALSE; - - for (ct = cd->ctors; ct != NULL; ct = ct->next) - { - if (ct->cppsig == NULL || !isPublicCtor(ct)) - continue; - - if (ct->cppsig->nrArgs == 0) - pub_def_ctor = TRUE; - else if (ct->cppsig->nrArgs == 1) - { - argDef *ad = &ct->cppsig->args[0]; - - if (ad->atype == class_type && ad->u.cd == cd && isReference(ad) && - isConstArg(ad) && ad->nrderefs == 0 && ad->defval == NULL) - pub_copy_ctor = TRUE; - } - } - - if (pub_def_ctor && pub_copy_ctor) - prcode(fp, -" qRegisterMetaType<%S>(\"%S\");\n" - , classFQCName(cd), classFQCName(cd)); -} - - -/* - * Generate the initialisation function or cast operators for the type. - */ -static void generateTypeInit(sipSpec *pt, classDef *cd, FILE *fp) -{ - ctorDef *ct; - int need_self, need_owner; - - /* - * See if we need to name the self and owner arguments so that we can - * avoid a compiler warning about an unused argument. - */ - need_self = (generating_c || hasShadow(cd)); - need_owner = generating_c; - - for (ct = cd->ctors; ct != NULL; ct = ct->next) - { - int a; - - if (usedInCode(ct->methodcode, "sipSelf")) - need_self = TRUE; - - for (a = 0; a < ct->pysig.nrArgs; ++a) - if (isThisTransferred(&ct->pysig.args[a])) - { - need_owner = TRUE; - break; - } - } - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static void *init_%C(sipWrapper *, PyObject *, sipWrapper **, int *);}\n" - , classFQCName(cd)); - - prcode(fp, -"static void *init_%C(sipWrapper *%s,PyObject *sipArgs,sipWrapper **%s,int *sipArgsParsed)\n" -"{\n" - ,classFQCName(cd),(need_self ? "sipSelf" : ""),(need_owner ? "sipOwner" : "")); - - if (hasShadow(cd)) - prcode(fp, -" sip%C *sipCpp = 0;\n" - ,classFQCName(cd)); - else - prcode(fp, -" %U *sipCpp = 0;\n" - ,cd); - - if (tracing) - prcode(fp, -"\n" -" sipTrace(SIP_TRACE_INITS,\"init_%C()\\n\");\n" - ,classFQCName(cd)); - - /* - * Generate the code that parses the Python arguments and calls the - * correct constructor. - */ - for (ct = cd->ctors; ct != NULL; ct = ct->next) - { - int needSecCall, error_flag = FALSE; - - if (isPrivateCtor(ct)) - continue; - - prcode(fp, -"\n" -" if (!sipCpp)\n" -" {\n" - ); - - if (ct->methodcode != NULL && needErrorFlag(ct->methodcode)) - { - prcode(fp, -" int sipIsErr = 0;\n" - ); - - error_flag = TRUE; - } - - needSecCall = generateArgParser(pt, &ct->pysig, cd, ct, NULL, FALSE, fp); - generateConstructorCall(cd,ct,error_flag,fp); - - if (needSecCall) - { - prcode(fp, -" }\n" -"\n" -" if (!sipCpp)\n" -" {\n" - ); - - if (error_flag) - prcode(fp, -" int sipIsErr = 0;\n" - ); - - generateArgParser(pt, &ct->pysig, cd, ct, NULL, TRUE, fp); - generateConstructorCall(cd,ct,error_flag,fp); - } - - prcode(fp, -" }\n" - ); - } - - if (hasShadow(cd)) - prcode(fp, -"\n" -" if (sipCpp)\n" -" sipCpp->sipPySelf = sipSelf;\n" - ); - - prcode(fp, -"\n" -" return sipCpp;\n" -"}\n" - ); -} - - -/* - * Count the number of virtual members in a class. - */ -static int countVirtuals(classDef *cd) -{ - int nrvirts; - virtOverDef *vod; - - nrvirts = 0; - - for (vod = cd->vmembers; vod != NULL; vod = vod->next) - if (!isPrivate(&vod->o)) - ++nrvirts; - - return nrvirts; -} - - -/* - * Generate the try block for a call. - */ -static void generateTry(throwArgs *ta,FILE *fp) -{ - /* - * Generate the block if there was no throw specifier, or a non-empty - * throw specifier. - */ - if (exceptions && (ta == NULL || ta->nrArgs > 0)) - prcode(fp, -" try\n" -" {\n" - ); -} - - -/* - * Generate the catch block for a call. - */ -static void generateCatch(throwArgs *ta, signatureDef *sd, FILE *fp) -{ - /* - * Generate the block if there was no throw specifier, or a non-empty - * throw specifier. - */ - if (exceptions && (ta == NULL || ta->nrArgs > 0)) - { - prcode(fp, -" }\n" - ); - - if (ta == NULL) - { - prcode(fp, -" catch (...)\n" -" {\n" - ); - - deleteTemps(sd, fp); - - if (release_gil) - prcode(fp, -" Py_BLOCK_THREADS\n" -"\n" - ); - - prcode(fp, -" sipRaiseUnknownException();\n" -" return NULL;\n" -" }\n" - ); - } - else - { - int a; - - for (a = 0; a < ta->nrArgs; ++a) - { - exceptionDef *xd = ta->args[a]; - scopedNameDef *ename = xd->iff->fqcname; - - prcode(fp, -" catch (%S &%s)\n" -" {\n" - ,ename,(xd->cd != NULL || usedInCode(xd->raisecode, "sipExceptionRef")) ? "sipExceptionRef" : ""); - - deleteTemps(sd, fp); - - if (xd->cd != NULL) - { - /* The exception is a wrapped class. */ - - prcode(fp, -" /* Hope that there is a valid copy ctor. */\n" -" %S *sipExceptionCopy = new %S(sipExceptionRef);\n" -"\n" - ,ename,ename); - - if (release_gil) - prcode(fp, -" Py_BLOCK_THREADS\n" -"\n" - ); - - prcode(fp, -" sipRaise%sClassException(sipClass_%C,sipExceptionCopy);\n" - ,(xd->cd->subbase != NULL ? "Sub" : ""),ename); - } - else - generateCppCodeBlock(xd->raisecode,fp); - - prcode(fp, -"\n" -" return NULL;\n" -" }\n" - ); - } - } - } -} - - -/* - * Generate a throw specifier. - */ -static void generateThrowSpecifier(throwArgs *ta,FILE *fp) -{ - if (exceptions && ta != NULL) - { - int a; - - prcode(fp," throw("); - - for (a = 0; a < ta->nrArgs; ++a) - { - if (a > 0) - prcode(fp,","); - - prcode(fp,"%S",ta->args[a]->iff->fqcname); - } - - prcode(fp,")"); - } -} - - -/* - * Generate a single constructor call. - */ -static void generateConstructorCall(classDef *cd,ctorDef *ct,int error_flag, - FILE *fp) -{ - prcode(fp, -" {\n" - ); - - /* Call any pre-hook. */ - if (ct->prehook != NULL) - prcode(fp, -" sipCallHook(\"%s\");\n" -"\n" - ,ct->prehook); - - if (ct->methodcode != NULL) - generateCppCodeBlock(ct->methodcode,fp); - else if (generating_c) - prcode(fp, -" sipCpp = sipMalloc(sizeof (%S));\n" - ,classFQCName(cd)); - else - { - int rgil = ((release_gil || isReleaseGILCtor(ct)) && !isHoldGILCtor(ct)); - - if (rgil) - prcode(fp, -" Py_BEGIN_ALLOW_THREADS\n" - ); - - generateTry(ct->exceptions,fp); - - if (hasShadow(cd)) - prcode(fp, -" sipCpp = new sip%C(",classFQCName(cd)); - else - prcode(fp, -" sipCpp = new %U(",cd); - - if (isCastCtor(ct)) - { - classDef *ocd; - - /* We have to fiddle the type to generate the correct code. */ - ocd = ct->pysig.args[0].u.cd; - ct->pysig.args[0].u.cd = cd; - prcode(fp, "a0->operator %B()", &ct->pysig.args[0]); - ct->pysig.args[0].u.cd = ocd; - } - else - generateArgs(ct->cppsig, Call, fp); - - prcode(fp,");\n" - ); - - generateCatch(ct->exceptions, &ct->pysig, fp); - - if (rgil) - prcode(fp, -" Py_END_ALLOW_THREADS\n" - ); - } - - gc_ellipsis(&ct->pysig, fp); - - deleteTemps(&ct->pysig, fp); - - if (error_flag) - prcode(fp, -"\n" -" if (sipIsErr)\n" -" return 0;\n" - ); - - /* Call any post-hook. */ - if (ct->posthook != NULL) - prcode(fp, -"\n" -" sipCallHook(\"%s\");\n" - ,ct->posthook); - - prcode(fp, -" }\n" - ); -} - - -/* - * See if a member overload should be skipped. - */ -static int skipOverload(overDef *od,memberDef *md,classDef *cd,classDef *ccd, - int want_local) -{ - /* Skip if it's not the right name. */ - if (od->common != md) - return TRUE; - - /* Skip if it's a signal. */ - if (isSignal(od)) - return TRUE; - - /* Skip if it's a private abstract. */ - if (isAbstract(od) && isPrivate(od)) - return TRUE; - - /* - * If we are disallowing them, skip if it's not in the current class - * unless it is protected. - */ - if (want_local && !isProtected(od) && ccd != cd) - return TRUE; - - return FALSE; -} - - -/* - * Generate a class member function. - */ -static void generateFunction(sipSpec *pt,memberDef *md,overDef *overs, - classDef *cd,classDef *ocd,FILE *fp) -{ - overDef *od; - int need_method, need_self, need_args, need_selfarg; - - /* - * Check that there is at least one overload that needs to be handled. - * See if we can avoid naming the "self" argument (and suppress a - * compiler warning). Finally see if we need to remember if "self" was - * explicitly passed as an argument. - */ - need_method = need_self = need_args = need_selfarg = FALSE; - - for (od = overs; od != NULL; od = od->next) - { - /* - * Skip protected methods if we don't have the means to handle - * them. - */ - if (isProtected(od) && !hasShadow(cd)) - continue; - - if (!skipOverload(od,md,cd,ocd,TRUE)) - { - need_method = TRUE; - - if (!isPrivate(od)) - { - need_args = TRUE; - - if (!isStatic(od)) - { - need_self = TRUE; - - if (isAbstract(od) || isVirtual(od) || isVirtualReimp(od) || usedInCode(od->methodcode, "sipSelfWasArg")) - need_selfarg = TRUE; - } - } - } - } - - if (need_method) - { - char *pname = md->pyname->text; - - prcode(fp, -"\n" -"\n" - ); - - if (!generating_c) - prcode(fp, -"extern \"C\" {static PyObject *meth_%C_%s(PyObject *, PyObject *);}\n" - , classFQCName(cd), pname); - - prcode(fp, -"static PyObject *meth_%C_%s(PyObject *%s,PyObject *%s)\n" -"{\n" - ,classFQCName(cd),pname,(need_self ? "sipSelf" : ""),(need_args ? "sipArgs" : "")); - - if (tracing) - prcode(fp, -" sipTrace(SIP_TRACE_METHODS,\"meth_%C_%s()\\n\");\n" -"\n" - ,classFQCName(cd),pname); - - if (need_args) - prcode(fp, -" int sipArgsParsed = 0;\n" - ); - - if (need_selfarg) - prcode(fp, -" bool sipSelfWasArg = !sipSelf;\n" - ); - - for (od = overs; od != NULL; od = od->next) - { - /* - * If we are handling one variant then we must handle - * them all. - */ - if (skipOverload(od,md,cd,ocd,FALSE)) - continue; - - if (isPrivate(od)) - continue; - - generateFunctionBody(pt,od,cd,ocd,TRUE,fp); - } - - prcode(fp, -"\n" -" /* Raise an exception if the arguments couldn't be parsed. */\n" -" sipNoMethod(%s,%N,%N);\n" -"\n" -" return NULL;\n" -"}\n" - ,(need_args ? "sipArgsParsed" : "0"),cd->iff->name,md->pyname); - } -} - - -/* - * Generate the function calls for a particular overload. - */ -static void generateFunctionBody(sipSpec *pt,overDef *od,classDef *cd, - classDef *ocd,int deref,FILE *fp) -{ - int needSecCall; - signatureDef saved; - - prcode(fp, -"\n" -" {\n" - ); - - /* In case we have to fiddle with it. */ - saved = od->pysig; - - if (isNumberSlot(od->common)) - { - /* - * Number slots must have two arguments because we parse them - * slightly differently. - */ - if (od->pysig.nrArgs == 1) - { - od->pysig.nrArgs = 2; - od->pysig.args[1] = od->pysig.args[0]; - - /* Insert self as the first argument. */ - od->pysig.args[0].atype = class_type; - od->pysig.args[0].name = NULL; - od->pysig.args[0].argflags = ARG_IS_REF|ARG_IN; - od->pysig.args[0].nrderefs = 0; - od->pysig.args[0].defval = NULL; - od->pysig.args[0].u.cd = ocd; - } - - generateArgParser(pt, &od->pysig, cd, NULL, od, FALSE, fp); - needSecCall = FALSE; - } - else if (isIntArgSlot(od->common) || isZeroArgSlot(od->common)) - needSecCall = FALSE; - else - needSecCall = generateArgParser(pt, &od->pysig, cd, NULL, od, FALSE, fp); - - generateFunctionCall(cd,ocd,od,deref,fp); - - if (needSecCall) - { - prcode(fp, -" }\n" -"\n" -" {\n" - ); - - generateArgParser(pt, &od->pysig, cd, NULL, od, TRUE, fp); - generateFunctionCall(cd,ocd,od,deref,fp); - } - - prcode(fp, -" }\n" - ); - - od->pysig = saved; -} - - -/* - * Generate the code to handle the result of a call to a member function. - */ -static void generateHandleResult(overDef *od,int isNew,char *prefix,FILE *fp) -{ - char *vname, vnamebuf[50]; - int a, nrvals, only, has_owner; - argDef *res, *ad; - - res = &od->pysig.result; - - if (res->atype == void_type && res->nrderefs == 0) - res = NULL; - - /* See if we are returning 0, 1 or more values. */ - nrvals = 0; - - if (res != NULL) - { - only = -1; - ++nrvals; - } - - has_owner = FALSE; - - for (a = 0; a < od->pysig.nrArgs; ++a) - { - if (isOutArg(&od->pysig.args[a])) - { - only = a; - ++nrvals; - } - - if (isThisTransferred(&od->pysig.args[a])) - has_owner = TRUE; - } - - /* Handle the trivial case. */ - if (nrvals == 0) - { - prcode(fp, -" Py_INCREF(Py_None);\n" -" %s Py_None;\n" - ,prefix); - - return; - } - - /* Handle results that are classes or mapped types separately. */ - if (res != NULL) - if (res->atype == mapped_type) - { - prcode(fp, -" PyObject *sipResObj = sipConvertFromMappedType("); - - if (isConstArg(res)) - prcode(fp,"const_cast<%b *>(sipRes)",res); - else - prcode(fp,"sipRes"); - - prcode(fp,",sipMappedType_%T,%s);\n" - , res, isResultTransferredBack(od) ? "Py_None" : "NULL"); - - if (isNew) - prcode(fp, -" delete sipRes;\n" - ); - - /* Shortcut if this is the only value returned. */ - if (nrvals == 1) - { - prcode(fp, -"\n" -" %s sipResObj;\n" - ,prefix); - - return; - } - } - else if (res->atype == class_type) - { - classDef *cd = res->u.cd; - - if (isNew || isFactory(od)) - { - prcode(fp, -" %s sipConvertFromNewInstance(",(nrvals == 1 ? prefix : "PyObject *sipResObj =")); - - if (isConstArg(res)) - prcode(fp,"const_cast<%b *>(sipRes)",res); - else - prcode(fp,"sipRes"); - - prcode(fp,",sipClass_%C,%s);\n" - ,classFQCName(cd),((has_owner && isFactory(od)) ? "(PyObject *)sipOwner" : "NULL")); - - /* - * Shortcut if this is the only value returned. - */ - if (nrvals == 1) - return; - } - else - { - prcode(fp, -" %s sipConvertFromInstance(",(nrvals == 1 ? prefix : "PyObject *sipResObj =")); - - if (isConstArg(res)) - prcode(fp,"const_cast<%b *>(sipRes)",res); - else - prcode(fp,"sipRes"); - - prcode(fp, ",sipClass_%C,%s);\n" - , classFQCName(cd), (isResultTransferredBack(od) ? "Py_None" : "NULL")); - - /* - * Shortcut if this is the only value returned. - */ - if (nrvals == 1) - return; - } - } - - /* If there are multiple values then build a tuple. */ - if (nrvals > 1) - { - prcode(fp, -" %s sipBuildResult(0,\"(",prefix); - - /* Build the format string. */ - if (res != NULL) - prcode(fp,"%c",((res->atype == mapped_type || res->atype == class_type) ? 'R' : getBuildResultFormat(res))); - - for (a = 0; a < od->pysig.nrArgs; ++a) - { - argDef *ad = &od->pysig.args[a]; - - if (isOutArg(ad)) - prcode(fp,"%c",getBuildResultFormat(ad)); - } - - prcode(fp,")\""); - - /* Pass the values for conversion. */ - if (res != NULL) - { - prcode(fp,",sipRes"); - - if (res->atype == mapped_type || res->atype == class_type) - prcode(fp,"Obj"); - else if (res->atype == enum_type && res->u.ed->fqcname != NULL) - prcode(fp,",sipEnum_%C",res->u.ed->fqcname); - } - - for (a = 0; a < od->pysig.nrArgs; ++a) - { - argDef *ad = &od->pysig.args[a]; - - if (isOutArg(ad)) - { - prcode(fp,",a%d",a); - - if (ad->atype == mapped_type) - prcode(fp, ",sipMappedType_%T,%s", ad, (isTransferredBack(ad) ? "Py_None" : "NULL")); - else if (ad->atype == class_type) - prcode(fp, ",sipClass_%C,%s", classFQCName(ad->u.cd), (isTransferredBack(ad) ? "Py_None" : "NULL")); - else if (ad->atype == enum_type && ad->u.ed->fqcname != NULL) - prcode(fp,",sipEnum_%C",ad->u.ed->fqcname); - } - } - - prcode(fp,");\n" - ); - - /* All done for multiple values. */ - return; - } - - /* Deal with the only returned value. */ - if (only < 0) - { - ad = res; - vname = "sipRes"; - } - else - { - ad = &od->pysig.args[only]; - - sprintf(vnamebuf,"a%d",only); - vname = vnamebuf; - } - - switch (ad->atype) - { - case mapped_type: - prcode(fp, -" %s sipConvertFromMappedType(", prefix); - - if (isConstArg(ad)) - prcode(fp,"const_cast<%b *>(%s)",ad,vname); - else - prcode(fp,"%s",vname); - - prcode(fp,",sipMappedType_%T,%s);\n" - , ad, (isTransferredBack(ad) ? "Py_None" : "NULL")); - - break; - - case class_type: - { - classDef *cd = ad->u.cd; - int needNew = needNewInstance(ad); - - if (needNew) - prcode(fp, -" %s sipConvertFromNewInstance(", prefix); - else - prcode(fp, -" %s sipConvertFromInstance(", prefix); - - if (isConstArg(ad)) - prcode(fp,"const_cast<%b *>(%s)",ad,vname); - else - prcode(fp,"%s",vname); - - prcode(fp,",sipClass_%C,",classFQCName(cd)); - - if (needNew) - prcode(fp,"NULL"); - else - prcode(fp,"%s\n" - , (isTransferredBack(ad) ? "Py_None" : "NULL")); - - prcode(fp,");\n" - ); - } - - break; - - case bool_type: - case cbool_type: - prcode(fp, -" %s PyBool_FromLong(%s);\n" - ,prefix,vname); - - break; - - case sstring_type: - case ustring_type: - case string_type: - if (ad->nrderefs == 0) - prcode(fp, -" %s PyString_FromStringAndSize(%s&%s,1);\n" - ,prefix,(ad->atype != string_type) ? "(char *)" : "",vname); - else - prcode(fp, -" if (%s == NULL)\n" -" {\n" -" Py_INCREF(Py_None);\n" -" return Py_None;\n" -" }\n" -"\n" -" %s PyString_FromString(%s%s);\n" - ,vname - ,prefix,(ad->atype != string_type) ? "(char *)" : "",vname); - - break; - - case wstring_type: - if (ad->nrderefs == 0) - prcode(fp, -" %s PyUnicode_FromWideChar(&%s,1);\n" - , prefix, vname); - else - prcode(fp, -" if (%s == NULL)\n" -" {\n" -" Py_INCREF(Py_None);\n" -" return Py_None;\n" -" }\n" -"\n" -" %s PyUnicode_FromWideChar(%s,(SIP_SSIZE_T)wcslen(%s));\n" - , vname - , prefix, vname, vname); - - break; - - case enum_type: - if (ad->u.ed->fqcname != NULL) - { - prcode(fp, -" %s sipConvertFromNamedEnum(%s,sipEnum_%C);\n" - ,prefix,vname,ad->u.ed->fqcname); - - break; - } - - /* Drop through. */ - - case short_type: - case int_type: - case cint_type: - prcode(fp, -" %s PyInt_FromLong(%s);\n" - ,prefix,vname); - - break; - - case long_type: - prcode(fp, -" %s PyLong_FromLong(%s);\n" - ,prefix,vname); - - break; - - case ushort_type: - case uint_type: - case ulong_type: - prcode(fp, -" %s PyLong_FromUnsignedLong(%s);\n" - ,prefix,vname); - - break; - - case longlong_type: - prcode(fp, -" %s PyLong_FromLongLong(%s);\n" - ,prefix,vname); - - break; - - case ulonglong_type: - prcode(fp, -" %s PyLong_FromUnsignedLongLong(%s);\n" - ,prefix,vname); - - break; - - case void_type: - prcode(fp, -" %s sipConvertFromVoidPtr(", prefix); - - if (isConstArg(ad)) - prcode(fp, "const_cast<void *>(%s)", vname); - else - prcode(fp, "%s", vname); - - prcode(fp, ");\n" - ); - - break; - - case struct_type: - prcode(fp, -" %s sipConvertFromVoidPtr(",prefix); - - if (isConstArg(ad)) - prcode(fp,"const_cast<%b *>(%s)",ad,vname); - else - prcode(fp,"%s",vname); - - prcode(fp,");\n" - ); - - break; - - case float_type: - case cfloat_type: - prcode(fp, -" %s PyFloat_FromDouble((double)%s);\n" - ,prefix,vname); - - break; - - case double_type: - case cdouble_type: - prcode(fp, -" %s PyFloat_FromDouble(%s);\n" - ,prefix,vname); - - break; - - case pyobject_type: - case pytuple_type: - case pylist_type: - case pydict_type: - case pycallable_type: - case pyslice_type: - case pytype_type: - prcode(fp, -" %s %s;\n" - ,prefix,vname); - - break; - } -} - - -/* - * Return the format character used by sipBuildResult() for a particular type. - */ -static char getBuildResultFormat(argDef *ad) -{ - switch (ad->atype) - { - case mapped_type: - return 'D'; - - case class_type: - if (needNewInstance(ad)) - return 'B'; - - return 'C'; - - case bool_type: - case cbool_type: - return 'b'; - - case sstring_type: - case ustring_type: - case string_type: - return (ad->nrderefs > (isOutArg(ad) ? 1 : 0)) ? 's' : 'c'; - - case wstring_type: - return (ad->nrderefs > (isOutArg(ad) ? 1 : 0)) ? 'x' : 'w'; - - case enum_type: - return (ad->u.ed->fqcname != NULL) ? 'E' : 'e'; - - case short_type: - return 'h'; - - case ushort_type: - return 't'; - - case int_type: - case cint_type: - return 'i'; - - case uint_type: - return 'u'; - - case long_type: - return 'l'; - - case ulong_type: - return 'm'; - - case longlong_type: - return 'n'; - - case ulonglong_type: - return 'o'; - - case void_type: - case struct_type: - return 'V'; - - case float_type: - case cfloat_type: - return 'f'; - - case double_type: - case cdouble_type: - return 'd'; - - case pyobject_type: - case pytuple_type: - case pylist_type: - case pydict_type: - case pycallable_type: - case pyslice_type: - case pytype_type: - return 'R'; - } - - /* We should never get here. */ - return ' '; -} - - -/* - * Generate a function call. - */ -static void generateFunctionCall(classDef *cd,classDef *ocd,overDef *od, - int deref, FILE *fp) -{ - int needsNew, error_flag = FALSE, newline, is_result, a, deltemps; - argDef *res = &od->pysig.result, orig_res; - - prcode(fp, -" {\n" - ); - - /* - * If there is no shadow class then protected methods can never be - * called. - */ - if (isProtected(od) && !hasShadow(cd)) - { - prcode(fp, -" /* Never reached. */\n" -" }\n" - ); - - return; - } - - /* Save the full result type as we may want to fiddle with it. */ - orig_res = *res; - - /* See if we need to make a copy of the result on the heap. */ - if ((res->atype == class_type || res->atype == mapped_type) && - !isReference(res) && - res->nrderefs == 0) - { - needsNew = TRUE; - resetIsConstArg(res); - } - else - needsNew = FALSE; - - /* See if sipRes is needed. */ - is_result = (!isInplaceNumberSlot(od->common) && - !isInplaceSequenceSlot(od->common) && - (res->atype != void_type || res->nrderefs != 0)); - - newline = FALSE; - - if (is_result) - { - prcode(fp, -" "); - - generateNamedValueType(res,"sipRes",fp); - - /* - * The typical %MethodCode usually causes a compiler warning, - * so we initialise the result in that case to try and suppress - * it. - */ - if (od->methodcode != NULL) - { - prcode(fp," = "); - - generateCastZero(res,fp); - } - - prcode(fp,";\n" - ); - - newline = TRUE; - } - - deltemps = TRUE; - - for (a = 0; a < od->pysig.nrArgs; ++a) - { - argDef *ad = &od->pysig.args[a]; - - /* - * If we have an In,Out argument that has conversion code then we delay - * the destruction of any temporary variables until after we have - * converted the outputs. - */ - if (isInArg(ad) && isOutArg(ad) && hasConvertToCode(ad) && deltemps) - { - deltemps = FALSE; - - prcode(fp, -" PyObject *sipResult;\n" - ); - - newline = TRUE; - } - - /* - * If we are returning a class via an output only reference or pointer - * then we need an instance on the heap. - */ - if (needNewInstance(ad)) - { - prcode(fp, -" a%d = new %b();\n" - ,a,ad); - - newline = TRUE; - } - } - - if (od->methodcode != NULL) - { - /* See if the handwritten code seems to be using the error flag. */ - if (needErrorFlag(od->methodcode)) - { - prcode(fp, -" int sipIsErr = 0;\n" - ); - - newline = TRUE; - error_flag = TRUE; - } - } - - if (newline) - prcode(fp, -"\n" - ); - - /* If it is abstract make sure that self was bound. */ - if (isAbstract(od)) - prcode(fp, -" if (sipSelfWasArg)\n" -" {\n" -" sipAbstractMethod(%N,%N);\n" -" return NULL;\n" -" }\n" -"\n" - , cd->iff->name, od->common->pyname); - - /* Call any pre-hook. */ - if (od->prehook != NULL) - prcode(fp, -" sipCallHook(\"%s\");\n" -"\n" - ,od->prehook); - - if (od->methodcode != NULL) - generateCppCodeBlock(od->methodcode,fp); - else - { - int rgil = ((release_gil || isReleaseGIL(od)) && !isHoldGIL(od)); - - if (needsNew && generating_c) - { - prcode(fp, -" if ((sipRes = (%b *)sipMalloc(sizeof (%b))) == NULL)\n" -" {\n" - ,res,res); - - gc_ellipsis(&od->pysig, fp); - - prcode(fp, -" return NULL;\n" -" }\n" -"\n" - ); - } - - if (rgil) - prcode(fp, -" Py_BEGIN_ALLOW_THREADS\n" - ); - - generateTry(od->exceptions,fp); - - prcode(fp, -" "); - - if (od->common->slot != cmp_slot && is_result) - { - /* Construct a copy on the heap if needed. */ - if (needsNew) - { - if (generating_c) - prcode(fp,"*sipRes = "); - else - prcode(fp,"sipRes = new %b(",res); - } - else - prcode(fp,"sipRes = "); - - /* See if we need the address of the result. */ - if ((res->atype == class_type || res->atype == mapped_type) && isReference(res)) - prcode(fp,"&"); - } - - switch (od->common->slot) - { - case no_slot: - generateCppFunctionCall(cd,ocd,od,fp); - break; - - case getitem_slot: - prcode(fp, "(*sipCpp)["); - generateSlotArg(&od->pysig, 0, fp); - prcode(fp,"]"); - break; - - case call_slot: - prcode(fp, "(*sipCpp)("); - generateArgs(od->cppsig,Call,fp); - prcode(fp,")"); - break; - - case int_slot: - case long_slot: - case float_slot: - prcode(fp, "*sipCpp"); - break; - - case add_slot: - generateNumberSlotCall(od,"+",fp); - break; - - case concat_slot: - generateBinarySlotCall(od,"+",deref,fp); - break; - - case sub_slot: - generateNumberSlotCall(od,"-",fp); - break; - - case mul_slot: - generateNumberSlotCall(od,"*",fp); - break; - - case repeat_slot: - generateBinarySlotCall(od,"*",deref,fp); - break; - - case div_slot: - generateNumberSlotCall(od,"/",fp); - break; - - case mod_slot: - generateNumberSlotCall(od,"%",fp); - break; - - case and_slot: - generateNumberSlotCall(od,"&",fp); - break; - - case or_slot: - generateNumberSlotCall(od,"|",fp); - break; - - case xor_slot: - generateNumberSlotCall(od,"^",fp); - break; - - case lshift_slot: - generateNumberSlotCall(od,"<<",fp); - break; - - case rshift_slot: - generateNumberSlotCall(od,">>",fp); - break; - - case iadd_slot: - case iconcat_slot: - generateBinarySlotCall(od,"+=",deref,fp); - break; - - case isub_slot: - generateBinarySlotCall(od,"-=",deref,fp); - break; - - case imul_slot: - case irepeat_slot: - generateBinarySlotCall(od,"*=",deref,fp); - break; - - case idiv_slot: - generateBinarySlotCall(od,"/=",deref,fp); - break; - - case imod_slot: - generateBinarySlotCall(od,"%=",deref,fp); - break; - - case iand_slot: - generateBinarySlotCall(od,"&=",deref,fp); - break; - - case ior_slot: - generateBinarySlotCall(od,"|=",deref,fp); - break; - - case ixor_slot: - generateBinarySlotCall(od,"^=",deref,fp); - break; - - case ilshift_slot: - generateBinarySlotCall(od,"<<=",deref,fp); - break; - - case irshift_slot: - generateBinarySlotCall(od,">>=",deref,fp); - break; - - case invert_slot: - prcode(fp, "~(*sipCpp)"); - break; - - case lt_slot: - generateBinarySlotCall(od,"<",deref,fp); - break; - - case le_slot: - generateBinarySlotCall(od,"<=",deref,fp); - break; - - case eq_slot: - generateBinarySlotCall(od,"==",deref,fp); - break; - - case ne_slot: - generateBinarySlotCall(od,"!=",deref,fp); - break; - - case gt_slot: - generateBinarySlotCall(od,">",deref,fp); - break; - - case ge_slot: - generateBinarySlotCall(od,">=",deref,fp); - break; - - case neg_slot: - prcode(fp, "-(*sipCpp)"); - break; - - case pos_slot: - prcode(fp, "+(*sipCpp)"); - break; - - case cmp_slot: - prcode(fp,"if "); - generateBinarySlotCall(od,"<",deref,fp); - prcode(fp,"\n" -" sipRes = -1;\n" -" else if "); - generateBinarySlotCall(od,">",deref,fp); - prcode(fp,"\n" -" sipRes = 1;\n" -" else\n" -" sipRes = 0"); - - break; - } - - if (needsNew && !generating_c) - prcode(fp,")"); - - prcode(fp,";\n" - ); - - generateCatch(od->exceptions, &od->pysig, fp); - - if (rgil) - prcode(fp, -" Py_END_ALLOW_THREADS\n" - ); - } - - /* Handle /TransferThis/ for non-factory methods. */ - if (!isFactory(od)) - for (a = 0; a < od->pysig.nrArgs; ++a) - { - argDef *ad = &od->pysig.args[a]; - - if (!isInArg(ad)) - continue; - - if (isThisTransferred(ad)) - { - prcode(fp, -"\n" -" if (sipOwner)\n" -" sipTransferTo(sipSelf, (PyObject *)sipOwner);\n" -" else\n" -" sipTransferBack(sipSelf);\n" - ); - - break; - } - } - - gc_ellipsis(&od->pysig, fp); - - if (deltemps) - deleteTemps(&od->pysig, fp); - - prcode(fp, -"\n" - ); - - /* Handle sipIsErr if it was used. */ - if (error_flag) - prcode(fp, -" if (sipIsErr)\n" -" return %s;\n" -"\n" - ,((isVoidReturnSlot(od->common) || isIntReturnSlot(od->common) || isLongReturnSlot(od->common)) ? "-1" : "0")); - - /* Call any post-hook. */ - if (od->posthook != NULL) - prcode(fp, -"\n" -" sipCallHook(\"%s\");\n" - ,od->posthook); - - if (isVoidReturnSlot(od->common)) - prcode(fp, -" return 0;\n" - ); - else if (isInplaceNumberSlot(od->common) || isInplaceSequenceSlot(od->common)) - prcode(fp, -" Py_INCREF(sipSelf);\n" -" return sipSelf;\n" - ); - else if (isIntReturnSlot(od->common) || isLongReturnSlot(od->common)) - prcode(fp, -" return sipRes;\n" - ); - else - { - generateHandleResult(od,needsNew,(deltemps ? "return" : "sipResult ="),fp); - - /* Delete the temporaries now if we haven't already done so. */ - if (!deltemps) - { - deleteTemps(&od->pysig, fp); - - prcode(fp, -"\n" -" return sipResult;\n" - ); - } - } - - prcode(fp, -" }\n" - ); - - /* Restore the full type of the result. */ - *res = orig_res; -} - - -/* - * Generate a call to a C++ function. - */ -static void generateCppFunctionCall(classDef *cd,classDef *ocd,overDef *od, - FILE *fp) -{ - char *mname = od->cppname; - int parens = 1; - - /* - * If the function is protected then call the public wrapper. If it is - * virtual then call explicit scoped function if "self" was passed as - * the first argument. - */ - - if (cd == NULL) - prcode(fp,"%s(",mname); - else if (cd->iff->type == namespace_iface) - prcode(fp,"%S::%s(",classFQCName(cd),mname); - else if (isStatic(od)) - { - if (isProtected(od)) - prcode(fp,"sip%C::sipProtect_%s(",classFQCName(cd),mname); - else - prcode(fp,"%S::%s(",classFQCName(ocd),mname); - } - else if (isProtected(od)) - { - if (!isAbstract(od) && (isVirtual(od) || isVirtualReimp(od))) - { - prcode(fp, "sipCpp->sipProtectVirt_%s(sipSelfWasArg", mname); - - if (od->cppsig->nrArgs > 0) - prcode(fp, ","); - } - else - prcode(fp, "sipCpp->sipProtect_%s(", mname); - } - else if (!isAbstract(od) && (isVirtual(od) || isVirtualReimp(od))) - { - prcode(fp, "(sipSelfWasArg ? sipCpp->%U::%s(", ocd, mname); - generateArgs(od->cppsig, Call, fp); - prcode(fp, ") : sipCpp->%s(", mname); - ++parens; - } - else - prcode(fp, "sipCpp->%s(", mname); - - generateArgs(od->cppsig, Call, fp); - - while (parens--) - prcode(fp, ")"); -} - - -/* - * Generate argument to a slot. - */ -static void generateSlotArg(signatureDef *sd, int argnr, FILE *fp) -{ - argDef *ad; - int deref; - - ad = &sd->args[argnr]; - deref = ((ad->atype == class_type || ad->atype == mapped_type) && ad->nrderefs == 0); - - prcode(fp, "%sa%d", (deref ? "*" : ""), argnr); -} - - -/* - * Generate the call to a binary (non-number) slot method. - */ -static void generateBinarySlotCall(overDef *od, char *op, int deref, FILE *fp) -{ - if (deref) - prcode(fp, "((*sipCpp) %s ", op); - else - prcode(fp, "(sipCpp %s ", op); - - generateSlotArg(&od->pysig, 0, fp); - prcode(fp, ")"); -} - - -/* - * Generate the call to a binary number slot method. - */ -static void generateNumberSlotCall(overDef *od, char *op, FILE *fp) -{ - prcode(fp, "("); - generateSlotArg(&od->pysig, 0, fp); - prcode(fp, " %s ", op); - generateSlotArg(&od->pysig, 1, fp); - prcode(fp, ")"); -} - - -/* - * Generate the argument variables for a member function/constructor/operator. - */ -static int generateArgParser(sipSpec *pt, signatureDef *sd, classDef *cd, - ctorDef *ct, overDef *od, int secCall, FILE *fp) -{ - int a, isQtSlot, optargs, arraylenarg, sigarg, handle_self; - int slotconarg, slotdisarg, need_owner; - - /* If the class is just a namespace, then ignore it. */ - - if (cd != NULL && cd->iff->type == namespace_iface) - cd = NULL; - - handle_self = (od != NULL && od->common->slot == no_slot && !isStatic(od) && cd != NULL); - - /* Assume there isn't a Qt slot. */ - - isQtSlot = FALSE; - - /* - * Generate the local variables that will hold the parsed arguments and - * values returned via arguments. - */ - - sigarg = -1; - need_owner = FALSE; - - for (a = 0; a < sd->nrArgs; ++a) - { - argDef *ad = &sd->args[a]; - - switch (ad->atype) - { - case signal_type: - sigarg = a; - break; - - case rxcon_type: - case rxdis_type: - isQtSlot = TRUE; - break; - - case slotcon_type: - slotconarg = a; - break; - - case slotdis_type: - slotdisarg = a; - break; - } - - if (isArraySize(ad)) - arraylenarg = a; - - generateVariable(ad,a,fp); - - if (isThisTransferred(ad)) - need_owner = TRUE; - } - - if (od != NULL && need_owner) - prcode(fp, -" sipWrapper *sipOwner = 0;\n" - ); - - if (handle_self) - { - if (isProtected(od) && hasShadow(cd)) - prcode(fp, -" sip%C *sipCpp;\n" - ,classFQCName(cd)); - else - prcode(fp, -" %U *sipCpp;\n" - ,cd); - - prcode(fp, -"\n" - ); - } - else if (sd->nrArgs != 0) - prcode(fp, -"\n" - ); - - /* Generate the call to the parser function. */ - if (od != NULL && isNumberSlot(od->common)) - prcode(fp, -" if (sipParsePair(%ssipArgsParsed,sipArg0,sipArg1,\"", (ct != NULL ? "" : "&")); - else - prcode(fp, -" if (sipParseArgs(%ssipArgsParsed,sipArg%s,\"", (ct != NULL ? "" : "&"), (od == NULL || od->common->slot == no_slot || isMultiArgSlot(od->common)) ? "s" : ""); - - /* Generate the format string. */ - optargs = FALSE; - - if (handle_self) - prcode(fp,"%c",(isProtected(od) ? 'p' : 'B')); - else if (isQtSlot && od == NULL) - prcode(fp,"C"); - - for (a = 0; a < sd->nrArgs; ++a) - { - char *fmt = ""; - argDef *ad = &sd->args[a]; - - if (!isInArg(ad)) - continue; - - if (ad->defval != NULL && !optargs) - { - prcode(fp,"|"); - optargs = TRUE; - } - - switch (ad->atype) - { - case sstring_type: - case ustring_type: - case string_type: - if (ad->nrderefs == 0 || (isOutArg(ad) && ad->nrderefs == 1)) - fmt = "c"; - else if (isArray(ad)) - fmt = "a"; - else - fmt = "s"; - - break; - - case wstring_type: - if (ad->nrderefs == 0 || (isOutArg(ad) && ad->nrderefs == 1)) - fmt = "w"; - else if (isArray(ad)) - fmt = "A"; - else - fmt = "x"; - - break; - - case enum_type: - fmt = (ad->u.ed->fqcname != NULL) ? "E" : "e"; - break; - - case bool_type: - fmt = "b"; - break; - - case cbool_type: - fmt = "Xb"; - break; - - case int_type: - if (!isArraySize(ad)) - fmt = "i"; - - break; - - case uint_type: - if (!isArraySize(ad)) - fmt = "u"; - - break; - - case cint_type: - fmt = "Xi"; - break; - - case short_type: - if (!isArraySize(ad)) - fmt = "h"; - - break; - - case ushort_type: - if (!isArraySize(ad)) - fmt = "t"; - - break; - - case long_type: - if (!isArraySize(ad)) - fmt = "l"; - - break; - - case ulong_type: - if (!isArraySize(ad)) - fmt = "m"; - - break; - - case longlong_type: - if (!isArraySize(ad)) - fmt = "n"; - - break; - - case ulonglong_type: - if (!isArraySize(ad)) - fmt = "o"; - - break; - - case struct_type: - case void_type: - fmt = "v"; - break; - - case float_type: - fmt = "f"; - break; - - case cfloat_type: - fmt = "Xf"; - break; - - case double_type: - fmt = "d"; - break; - - case cdouble_type: - fmt = "Xd"; - break; - - case signal_type: - fmt = "G"; - break; - - case slot_type: - fmt = "S"; - break; - - case anyslot_type: - fmt = "U"; - break; - - case slotcon_type: - case slotdis_type: - fmt = (secCall ? "" : "S"); - break; - - case rxcon_type: - fmt = (secCall ? "y" : "q"); - break; - - case rxdis_type: - fmt = (secCall ? "Y" : "Q"); - break; - - case mapped_type: - fmt = getSubFormatChar('M',ad); - break; - - case class_type: - fmt = getSubFormatChar('J', ad); - break; - - case pyobject_type: - fmt = getSubFormatChar('P',ad); - break; - - case pytuple_type: - case pylist_type: - case pydict_type: - case pyslice_type: - case pytype_type: - fmt = (isAllowNone(ad) ? "N" : "T"); - break; - - case pycallable_type: - fmt = (isAllowNone(ad) ? "H" : "F"); - break; - - case qobject_type: - fmt = "R"; - break; - - case ellipsis_type: - fmt = "W"; - break; - } - - prcode(fp,fmt); - } - - prcode(fp,"\""); - - /* Generate the parameters corresponding to the format string. */ - - if (handle_self) - prcode(fp,",&sipSelf,sipClass_%C,&sipCpp",classFQCName(cd)); - else if (isQtSlot && od == NULL) - prcode(fp,",sipSelf"); - - for (a = 0; a < sd->nrArgs; ++a) - { - argDef *ad = &sd->args[a]; - - if (!isInArg(ad)) - continue; - - switch (ad->atype) - { - case mapped_type: - prcode(fp,",sipMappedType_%T,&a%d,&a%dState",ad,a,a); - break; - - case class_type: - prcode(fp, ",sipClass_%T,&a%d", ad, a); - - if (isThisTransferred(ad)) - prcode(fp, ",%ssipOwner", (ct != NULL ? "" : "&")); - else if (isGetWrapper(ad)) - prcode(fp, ",&a%dWrapper", a); - - if (ad->u.cd->convtocode != NULL && !isConstrained(ad)) - prcode(fp, ",&a%dState", a); - - break; - - case rxcon_type: - { - if (sigarg > 0) - prcode(fp,",a%d",sigarg); - else - { - prcode(fp,",\"("); - - generateArgs(sd->args[slotconarg].u.sa,Declaration,fp); - - prcode(fp,")\""); - } - - prcode(fp,",&a%d,&a%d",a,slotconarg); - - break; - } - - case rxdis_type: - { - prcode(fp,",\"("); - - generateArgs(sd->args[slotdisarg].u.sa,Declaration,fp); - - prcode(fp,")\",&a%d,&a%d",a,slotdisarg); - - break; - } - - case slotcon_type: - case slotdis_type: - if (!secCall) - prcode(fp,",&a%d",a); - - break; - - case anyslot_type: - prcode(fp, ",&a%dName,&a%dCallable", a, a); - break; - - case pytuple_type: - prcode(fp,",&PyTuple_Type,&a%d",a); - break; - - case pylist_type: - prcode(fp,",&PyList_Type,&a%d",a); - break; - - case pydict_type: - prcode(fp,",&PyDict_Type,&a%d",a); - break; - - case pyslice_type: - prcode(fp,",&PySlice_Type,&a%d",a); - break; - - case pytype_type: - prcode(fp,",&PyType_Type,&a%d",a); - break; - - case enum_type: - if (ad->u.ed->fqcname != NULL) - prcode(fp,",sipEnum_%C",ad->u.ed->fqcname); - - prcode(fp,",&a%d",a); - break; - - default: - if (!isArraySize(ad)) - prcode(fp,",&a%d",a); - - if (isArray(ad)) - prcode(fp,",&a%d",arraylenarg); - } - } - - prcode(fp,"))\n"); - - return isQtSlot; -} - - -/* - * Get the format character string for something that has sub-formats. - */ - -static char *getSubFormatChar(char fc,argDef *ad) -{ - static char fmt[3]; - char flags; - - fmt[0] = fc; - - flags = 0; - - if (fc != 'P' && ad->nrderefs == 0) - flags |= 0x01; - - if (isTransferred(ad)) - flags |= 0x02; - - if (isTransferredBack(ad)) - flags |= 0x04; - - if (fc == 'J') - { - if (isThisTransferred(ad)) - flags |= 0x20; - - if (isGetWrapper(ad)) - flags |= 0x08; - - if (ad->u.cd->convtocode == NULL || isConstrained(ad)) - flags |= 0x10; - } - - fmt[1] = '0' + flags; - - fmt[2] = '\0'; - - return fmt; -} - - -/* - * Return TRUE if a type has %ConvertToTypeCode. - */ -static int hasConvertToCode(argDef *ad) -{ - codeBlock *convtocode; - - if (ad->atype == class_type && !isConstrained(ad)) - convtocode = ad->u.cd->convtocode; - else if (ad->atype == mapped_type) - convtocode = ad->u.mtd->convtocode; - else - convtocode = NULL; - - return (convtocode != NULL); -} - - -/* - * Garbage collect any ellipsis argument. - */ -static void gc_ellipsis(signatureDef *sd, FILE *fp) -{ - if (sd->nrArgs > 0 && sd->args[sd->nrArgs - 1].atype == ellipsis_type) - prcode(fp, -"\n" -" Py_DECREF(a%d);\n" - , sd->nrArgs - 1); -} - - -/* - * Delete any temporary variables on the heap created by type convertors. - */ -static void deleteTemps(signatureDef *sd, FILE *fp) -{ - int a, first = TRUE; - - for (a = 0; a < sd->nrArgs; ++a) - { - argDef *ad = &sd->args[a]; - - if (!isInArg(ad)) - continue; - - if (ad->atype == wstring_type && ad->nrderefs == 1) - { - if (generating_c || !isConstArg(ad)) - prcode(fp, -" sipFree(a%d);\n" - , a); - else - prcode(fp, -" sipFree(const_cast<wchar_t *>(a%d));\n" - , a); - } - else if (hasConvertToCode(ad)) - { - const char *fstr, *sstr; - - if (ad->atype == mapped_type) - fstr = sstr = "MappedType"; - else - { - fstr = "Instance"; - sstr = "Class"; - } - - if (first) - { - prcode(fp, -"\n" - ); - - first = FALSE; - } - - if (generating_c || !isConstArg(ad)) - prcode(fp, -" sipRelease%s(a%d,sip%s_%T,a%dState);\n" - , fstr, a, sstr, ad, a); - else - prcode(fp, -" sipRelease%s(const_cast<%b *>(a%d),sip%s_%T,a%dState);\n" - , fstr, ad, a, sstr, ad, a); - } - } -} - - -/* - * Generate a C++ code block. - */ -static void generateCppCodeBlock(codeBlock *code,FILE *fp) -{ - int reset_line = FALSE; - codeBlock *cb; - - for (cb = code; cb != NULL; cb = cb->next) - { - char *cp; - - /* - * Fragmented fragments (possibly created when applying - * template types) don't have a filename. - */ - if ((cp = cb->filename) != NULL) - { - reset_line = TRUE; - - prcode(fp, -"#line %d \"", cb->linenr); - - while (*cp != '\0') - { - prcode(fp, "%c", *cp); - - if (*cp == '\\') - prcode(fp, "\\"); - - ++cp; - } - - prcode(fp, "\"\n" - ); - } - - prcode(fp, "%s", cb->frag); - } - - if (reset_line) - { - char *bn; - - /* Just use the base name. */ - - if ((bn = strrchr(currentFileName,'/')) != NULL) - ++bn; - else - bn = currentFileName; - - prcode(fp, -"#line %d \"%s\"\n" - ,currentLineNr + 1,bn); - } -} - - -/* - * Create a source file. - */ -static FILE *createCompilationUnit(sipSpec *pt, char *fname, char *description) -{ - FILE *fp = createFile(pt, fname, description); - - if (fp != NULL) - generateCppCodeBlock(pt->unitcode, fp); - - return fp; -} - - -/* - * Create a file with an optional standard header. - */ -static FILE *createFile(sipSpec *pt,char *fname,char *description) -{ - FILE *fp; - - /* Create the file. */ - - if ((fp = fopen(fname,"w")) == NULL) - fatal("Unable to create file \"%s\"\n",fname); - - /* The "stack" doesn't have to be very deep. */ - previousLineNr = currentLineNr; - currentLineNr = 1; - previousFileName = currentFileName; - currentFileName = fname; - - if (description != NULL) - { - int needComment; - codeBlock *cb; - time_t now; - - /* Write the header. */ - now = time(NULL); - - prcode(fp, -"/*\n" -" * %s\n" -" *\n" -" * Generated by SIP %s on %s" - ,description - ,sipVersion,ctime(&now)); - - if (pt->copying != NULL) - prcode(fp, -" *\n" - ); - - needComment = TRUE; - - for (cb = pt->copying; cb != NULL; cb = cb->next) - { - char *cp; - - for (cp = cb->frag; *cp != '\0'; ++cp) - { - if (needComment) - { - needComment = FALSE; - prcode(fp," * "); - } - - prcode(fp,"%c",*cp); - - if (*cp == '\n') - needComment = TRUE; - } - } - - prcode(fp, -" */\n" - ); - } - - return fp; -} - - -/* - * Close a file and report any errors. - */ -static void closeFile(FILE *fp) -{ - if (ferror(fp)) - fatal("Error writing to \"%s\"\n",currentFileName); - - if (fclose(fp)) - fatal("Error closing \"%s\"\n",currentFileName); - - currentLineNr = previousLineNr; - currentFileName = previousFileName; -} - - -/* - * Print formatted code. - */ -void prcode(FILE *fp, const char *fmt, ...) -{ - char ch; - va_list ap; - - prcode_last = fmt; - - va_start(ap,fmt); - - while ((ch = *fmt++) != '\0') - if (ch == '%') - { - ch = *fmt++; - - switch (ch) - { - case 'c': - { - char c = (char)va_arg(ap,int); - - if (c == '\n') - ++currentLineNr; - - fputc(c,fp); - break; - } - - case 's': - { - const char *cp = va_arg(ap,const char *); - - while (*cp != '\0') - { - if (*cp == '\n') - ++currentLineNr; - - fputc(*cp,fp); - ++cp; - } - - break; - } - - case 'l': - fprintf(fp,"%ld",va_arg(ap,long)); - break; - - case 'u': - fprintf(fp,"%u",va_arg(ap,unsigned)); - break; - - case 'd': - fprintf(fp,"%d",va_arg(ap,int)); - break; - - case 'g': - fprintf(fp,"%g",va_arg(ap,double)); - break; - - case 'x': - fprintf(fp,"0x%08x",va_arg(ap,unsigned)); - break; - - case '\0': - fputc('%',fp); - --fmt; - break; - - case '\n': - fputc('\n',fp); - ++currentLineNr; - break; - - case 'b': - { - argDef *ad, orig; - - ad = va_arg(ap,argDef *); - orig = *ad; - - resetIsConstArg(ad); - resetIsReference(ad); - ad->nrderefs = 0; - - generateBaseType(ad,fp); - - *ad = orig; - - break; - } - - case 'M': - prcode_xml = !prcode_xml; - break; - - case 'B': - generateBaseType(va_arg(ap,argDef *),fp); - break; - - case 'T': - prTypeName(fp,va_arg(ap,argDef *),FALSE); - break; - - case 'I': - { - int indent = va_arg(ap,int); - - while (indent-- > 0) - fputc('\t',fp); - - break; - } - - case 'N': - { - nameDef *nd = va_arg(ap,nameDef *); - - fprintf(fp,"sipNm_%s_%s",nd->module->name,nd->text); - break; - } - - case 'E': - { - enumDef *ed = va_arg(ap,enumDef *); - - if (ed->fqcname == NULL) - fprintf(fp,"int"); - else if (isProtectedEnum(ed)) - { - fprintf(fp,"sip"); - prScopedName(fp,classFQCName(ed->pcd),"_"); - - fprintf(fp,"::sip%s",scopedNameTail(ed->fqcname)); - } - else - prScopedName(fp,ed->fqcname,"::"); - - break; - } - - case 'F': - prScopedName(fp,va_arg(ap,scopedNameDef *),""); - break; - - case 'C': - prScopedName(fp,va_arg(ap,scopedNameDef *),"_"); - break; - - case 'S': - if (generating_c) - fprintf(fp,"struct "); - - prScopedName(fp,va_arg(ap,scopedNameDef *),"::"); - break; - - case 'U': - if (generating_c) - fprintf(fp,"struct "); - - prScopedClassName(fp,va_arg(ap,classDef *),"::"); - break; - - case 'O': - prOverloadName(fp, va_arg(ap, overDef *)); - break; - - case 'P': - { - classDef *ecd = va_arg(ap, classDef *); - const char *pyname = va_arg(ap, const char *); - - prScopedPythonName(fp, ecd, pyname); - break; - } - - case 'X': - generateThrowSpecifier(va_arg(ap,throwArgs *),fp); - break; - - default: - fputc(ch,fp); - } - } - else if (ch == '\n') - { - fputc('\n',fp); - ++currentLineNr; - } - else - fputc(ch,fp); - - va_end(ap); -} - - -/* - * Generate the C++ name of an overloaded function. - */ -void prOverloadName(FILE *fp, overDef *od) -{ - char *pt1, *pt2; - - pt1 = "operator"; - - switch (od->common->slot) - { - case add_slot: - pt2 = "+"; - break; - - case sub_slot: - pt2 = "-"; - break; - - case mul_slot: - pt2 = "*"; - break; - - case div_slot: - pt2 = "/"; - break; - - case mod_slot: - pt2 = "%"; - break; - - case and_slot: - pt2 = "&"; - break; - - case or_slot: - pt2 = "|"; - break; - - case xor_slot: - pt2 = "^"; - break; - - case lshift_slot: - pt2 = "<<"; - break; - - case rshift_slot: - pt2 = ">>"; - break; - - case iadd_slot: - pt2 = "+="; - break; - - case isub_slot: - pt2 = "-="; - break; - - case imul_slot: - pt2 = "*="; - break; - - case idiv_slot: - pt2 = "/="; - break; - - case imod_slot: - pt2 = "%="; - break; - - case iand_slot: - pt2 = "&="; - break; - - case ior_slot: - pt2 = "|="; - break; - - case ixor_slot: - pt2 = "^="; - break; - - case ilshift_slot: - pt2 = "<<="; - break; - - case irshift_slot: - pt2 = ">>="; - break; - - case invert_slot: - pt2 = "~"; - break; - - case call_slot: - pt2 = "()"; - break; - - case getitem_slot: - pt2 = "[]"; - break; - - case lt_slot: - pt2 = "<"; - break; - - case le_slot: - pt2 = "<="; - break; - - case eq_slot: - pt2 = "=="; - break; - - case ne_slot: - pt2 = "!="; - break; - - case gt_slot: - pt2 = ">"; - break; - - case ge_slot: - pt2 = ">="; - break; - - default: - pt1 = ""; - pt2 = od->cppname; - } - - fprintf(fp, "%s%s", pt1, pt2); -} - - -/* - * Generate a scoped name with the given separator string. - */ -static void prScopedName(FILE *fp,scopedNameDef *snd,char *sep) -{ - while (snd != NULL) - { - fprintf(fp,"%s",snd->name); - - if ((snd = snd->next) != NULL) - fprintf(fp,"%s",sep); - } -} - - -/* - * Generate a scoped class name with the given separator string. At the moment - * this provides (probably) broken support for protected classes. - */ -static void prScopedClassName(FILE *fp,classDef *cd,char *sep) -{ - scopedNameDef *snd = classFQCName(cd); - - while (snd != NULL) - { - if (isProtectedClass(cd)) - fprintf(fp,"sip"); - - fprintf(fp,"%s",snd->name); - - if ((snd = snd->next) != NULL) - fprintf(fp,"%s",sep); - } -} - - -/* - * Generate a scoped Python name. - */ -void prScopedPythonName(FILE *fp, classDef *scope, const char *pyname) -{ - if (scope != NULL) - { - prScopedPythonName(fp, scope->ecd, NULL); - fprintf(fp, "%s.", scope->pyname); - } - - if (pyname != NULL) - fprintf(fp, "%s", pyname); -} - - -/* - * Generate a type name to be used as part of an identifier name. - */ -static void prTypeName(FILE *fp,argDef *ad,int intmpl) -{ - if (intmpl) - { - char buf[10]; - int flgs; - - /* We use numbers so they don't conflict with names. */ - - sprintf(buf,"%02d",ad->atype); - - flgs = 0; - - if (isConstArg(ad)) - flgs += 1; - - if (isReference(ad)) - flgs += 2; - - prcode(fp,"%s%d%d",buf,flgs,ad->nrderefs); - } - - /* Now add a name if there is one associated with the type. */ - - switch (ad->atype) - { - case struct_type: - prcode(fp,"%C",ad->u.sname); - break; - - case defined_type: - prcode(fp,"%C",ad->u.snd); - break; - - case enum_type: - prcode(fp,"%C",ad->u.ed->fqcname); - break; - - case mapped_type: - prTypeName(fp,&ad->u.mtd->type,intmpl); - break; - - case class_type: - prcode(fp,"%C",classFQCName(ad->u.cd)); - break; - - case template_type: - { - int a; - templateDef *td = ad->u.td; - - prcode(fp,"%C",td->fqname); - - for (a = 0; a < td->types.nrArgs; ++a) - { - prcode(fp,"_"); - prTypeName(fp,&td->types.args[a],TRUE); - } - - break; - } - } -} - - -/* - * Return TRUE if handwritten code uses the error flag. - */ -static int needErrorFlag(codeBlock *cb) -{ - return usedInCode(cb, "sipIsErr"); -} - - -/* - * Return TRUE if the argument type means an instance needs to be created on - * the heap to pass back to Python. - */ -static int needNewInstance(argDef *ad) -{ - return ((ad->atype == mapped_type || ad->atype == class_type) && - ((isReference(ad) && ad->nrderefs == 0) || (!isReference(ad) && ad->nrderefs == 1)) && - !isInArg(ad) && isOutArg(ad)); -} - - -/* - * Reset and save any argument flags so that the signature will be rendered - * exactly as defined in C++. - */ -static void normaliseArgs(signatureDef *sd) -{ - int a; - argDef *ad = sd->args; - - for (a = 0; a < sd->nrArgs; ++a) - { - if (ad->atype == class_type && isProtectedClass(ad->u.cd)) - { - resetIsProtectedClass(ad->u.cd); - setWasProtectedClass(ad->u.cd); - } - else if (ad->atype == enum_type && isProtectedEnum(ad->u.ed)) - { - resetIsProtectedEnum(ad->u.ed); - setWasProtectedEnum(ad->u.ed); - } - - ++ad; - } -} - - -/* - * Restore any argument flags modified by normaliseArgs(). - */ -static void restoreArgs(signatureDef *sd) -{ - int a; - argDef *ad = sd->args; - - for (a = 0; a < sd->nrArgs; ++a) - { - if (ad->atype == class_type && wasProtectedClass(ad->u.cd)) - { - resetWasProtectedClass(ad->u.cd); - setIsProtectedClass(ad->u.cd); - } - else if (ad->atype == enum_type && wasProtectedEnum(ad->u.ed)) - { - resetWasProtectedEnum(ad->u.ed); - setIsProtectedEnum(ad->u.ed); - } - - ++ad; - } -} - - -/* - * Return TRUE if a dealloc function is needed for a class. - */ -static int needDealloc(classDef *cd) -{ - if (cd->iff->type == namespace_iface) - return FALSE; - - /* All of these conditions cause some code to be generated. */ - - if (tracing) - return TRUE; - - if (generating_c) - return TRUE; - - if (cd->dealloccode != NULL) - return TRUE; - - if (isPublicDtor(cd)) - return TRUE; - - if (hasShadow(cd)) - return TRUE; - - return FALSE; -} - - -/* - * Return the argument name to use in a function definition for handwritten - * code. - */ -static const char *argName(const char *name, codeBlock *cb) -{ - static const char noname[] = ""; - - /* Always use the name in C code. */ - if (generating_c) - return name; - - /* Use the name if it is used in the handwritten code. */ - if (usedInCode(cb, name)) - return name; - - /* Don't use the name and avoid a compiler warning. */ - return noname; -} - - -/* - * Returns TRUE if a string is used in a code block. - */ -static int usedInCode(codeBlock *code, const char *str) -{ - while (code != NULL) - { - if (strstr(code->frag, str) != NULL) - return TRUE; - - code = code->next; - } - - return FALSE; -} - - -/* - * Generate an assignment statement from a void * variable to a class instance - * variable. - */ -static void generateClassFromVoid(classDef *cd, const char *cname, - const char *vname, FILE *fp) -{ - if (generating_c) - prcode(fp, "%S *%s = (%S *)%s", classFQCName(cd), cname, classFQCName(cd), vname); - else - prcode(fp, "%S *%s = reinterpret_cast<%S *>(%s)", classFQCName(cd), cname, classFQCName(cd), vname); -} - - -/* - * Generate an assignment statement from a void * variable to a mapped type - * variable. - */ -static void generateMappedTypeFromVoid(mappedTypeDef *mtd, const char *cname, - const char *vname, FILE *fp) -{ - if (generating_c) - prcode(fp, "%b *%s = (%b *)%s", &mtd->type, cname, &mtd->type, vname); - else - prcode(fp, "%b *%s = reinterpret_cast<%b *>(%s)", &mtd->type, cname, &mtd->type, vname); -} |