📄 gencode.c
字号:
/* * The code generator module for SIP. * * Copyright (c) 2006 * Riverbank Computing Limited <info@riverbankcomputing.co.uk> * * This file is part of SIP. * * This copy of SIP is licensed for use under the terms of the SIP License * Agreement. See the file LICENSE for more details. * * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */#include <stdio.h>#include <time.h>#include <errno.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include "sip.h"/* 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;/* An API definition. */typedef struct _apiDef { char *name; /* The function name. */ signatureDef *sd; /* The function signature. */ struct _apiDef *next; /* The next in the list. */} apiDef;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 char *prcode_last = NULL; /* The last prcode format string. */static void generateDocumentation(sipSpec *,char *);static void generateAPI(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 void generateResultType(argDef *,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 generateExpression(valueDef *,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 void addUniqueAPI(apiDef **,char *,signatureDef *);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 *createFile(sipSpec *,char *,char *);static void closeFile(FILE *);static void prcode(FILE *,char *,...);static void prScopedName(FILE *,scopedNameDef *,char *);static void prScopedPythonName(FILE *fp, classDef *scope, char *pyname);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);/* * Generate the code from a specification. */void generateCode(sipSpec *pt,char *codeDir,char *buildfile,char *docFile, char *apiFile,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 API file. */ if (apiFile != NULL) generateAPI(pt,apiFile);}/* * Generate the Scintilla API file. */static void generateAPI(sipSpec *pt,char *apiFile){ apiDef *head, *ad; overDef *od; classDef *cd; FILE *fp; /* Create the list of unique names/signatures. */ head = NULL; for (od = pt -> overs; od != NULL; od = od -> next) addUniqueAPI(&head,od -> cppname,&od -> pysig); for (cd = pt -> classes; cd != NULL; cd = cd -> next) { ctorDef *ct; if (cd -> iff -> module != pt -> module) continue; for (ct = cd -> ctors; ct != NULL; ct = ct -> next) { if (isPrivateCtor(ct)) continue; addUniqueAPI(&head,classBaseName(cd),&ct -> pysig); } for (od = cd -> overs; od != NULL; od = od -> next) { if (isPrivate(od)) continue; addUniqueAPI(&head,od -> cppname,&od -> pysig); } } /* Generate the file. */ fp = createFile(pt,apiFile,NULL); for (ad = head; ad != NULL; ad = ad -> next) { fprintf(fp,"%s(",ad -> name); generateArgs(ad -> sd,Declaration,fp); fprintf(fp,")\n"); } closeFile(fp);}/* * Add an API function to a list if it isn't already there. */static void addUniqueAPI(apiDef **headp,char *name,signatureDef *sd){ apiDef *ad; for (ad = *headp; ad != NULL; ad = ad -> next) { if (strcmp(ad -> name,name) != 0) continue; if (sameSignature(ad -> sd,sd,TRUE)) break; } if (ad == NULL) { ad = sipMalloc(sizeof (apiDef)); ad -> name = name; ad -> sd = sd; ad -> next = *headp; *headp = ad; }}/* * 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++. */static 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: 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); /* 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 -> 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"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -