From 8d2407d5536d111a017f346cccb53d04e23c2d66 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 10 Aug 2024 16:20:50 +0200 Subject: [PATCH] Delete cppparser and interrogate from tree These tools now live in https://github.com/panda3d/interrogate/ See also #1074 --- dtool/src/cppparser/CMakeLists.txt | 46 - dtool/src/cppparser/cppArrayType.cxx | 269 - dtool/src/cppparser/cppArrayType.h | 65 - dtool/src/cppparser/cppAttributeList.cxx | 196 - dtool/src/cppparser/cppAttributeList.h | 65 - dtool/src/cppparser/cppBison.cxx.prebuilt | 10080 ---------------- dtool/src/cppparser/cppBison.h.prebuilt | 394 - dtool/src/cppparser/cppBison.yxx | 4455 ------- dtool/src/cppparser/cppBisonDefs.h | 124 - .../cppparser/cppClassTemplateParameter.cxx | 126 - .../src/cppparser/cppClassTemplateParameter.h | 47 - dtool/src/cppparser/cppClosureType.cxx | 200 - dtool/src/cppparser/cppClosureType.h | 65 - dtool/src/cppparser/cppCommentBlock.cxx | 14 - dtool/src/cppparser/cppCommentBlock.h | 41 - dtool/src/cppparser/cppConstType.cxx | 240 - dtool/src/cppparser/cppConstType.h | 66 - dtool/src/cppparser/cppDeclaration.cxx | 379 - dtool/src/cppparser/cppDeclaration.h | 239 - dtool/src/cppparser/cppEnumType.cxx | 328 - dtool/src/cppparser/cppEnumType.h | 71 - dtool/src/cppparser/cppExpression.cxx | 2450 ---- dtool/src/cppparser/cppExpression.h | 203 - dtool/src/cppparser/cppExpressionParser.cxx | 77 - dtool/src/cppparser/cppExpressionParser.h | 48 - dtool/src/cppparser/cppExtensionType.cxx | 281 - dtool/src/cppparser/cppExtensionType.h | 81 - dtool/src/cppparser/cppFile.cxx | 144 - dtool/src/cppparser/cppFile.h | 63 - dtool/src/cppparser/cppFunctionGroup.cxx | 92 - dtool/src/cppparser/cppFunctionGroup.h | 47 - dtool/src/cppparser/cppFunctionType.cxx | 463 - dtool/src/cppparser/cppFunctionType.h | 101 - dtool/src/cppparser/cppGlobals.cxx | 16 - dtool/src/cppparser/cppGlobals.h | 26 - dtool/src/cppparser/cppIdentifier.cxx | 612 - dtool/src/cppparser/cppIdentifier.h | 106 - dtool/src/cppparser/cppInstance.cxx | 637 - dtool/src/cppparser/cppInstance.h | 138 - dtool/src/cppparser/cppInstanceIdentifier.cxx | 345 - dtool/src/cppparser/cppInstanceIdentifier.h | 115 - dtool/src/cppparser/cppMakeProperty.cxx | 122 - dtool/src/cppparser/cppMakeProperty.h | 116 - dtool/src/cppparser/cppMakeSeq.cxx | 81 - dtool/src/cppparser/cppMakeSeq.h | 50 - dtool/src/cppparser/cppManifest.cxx | 672 -- dtool/src/cppparser/cppManifest.h | 100 - dtool/src/cppparser/cppNameComponent.cxx | 167 - dtool/src/cppparser/cppNameComponent.h | 56 - dtool/src/cppparser/cppNamespace.cxx | 116 - dtool/src/cppparser/cppNamespace.h | 52 - dtool/src/cppparser/cppParameterList.cxx | 239 - dtool/src/cppparser/cppParameterList.h | 66 - dtool/src/cppparser/cppParser.cxx | 93 - dtool/src/cppparser/cppParser.h | 52 - dtool/src/cppparser/cppPointerType.cxx | 308 - dtool/src/cppparser/cppPointerType.h | 64 - dtool/src/cppparser/cppPreprocessor.cxx | 3305 ----- dtool/src/cppparser/cppPreprocessor.h | 235 - dtool/src/cppparser/cppReferenceType.cxx | 296 - dtool/src/cppparser/cppReferenceType.h | 70 - dtool/src/cppparser/cppScope.cxx | 1191 -- dtool/src/cppparser/cppScope.h | 165 - dtool/src/cppparser/cppSimpleType.cxx | 288 - dtool/src/cppparser/cppSimpleType.h | 100 - dtool/src/cppparser/cppStructType.cxx | 1546 --- dtool/src/cppparser/cppStructType.h | 132 - dtool/src/cppparser/cppTBDType.cxx | 175 - dtool/src/cppparser/cppTBDType.h | 62 - .../cppparser/cppTemplateParameterList.cxx | 234 - .../src/cppparser/cppTemplateParameterList.h | 76 - dtool/src/cppparser/cppTemplateScope.cxx | 172 - dtool/src/cppparser/cppTemplateScope.h | 58 - dtool/src/cppparser/cppToken.cxx | 1327 -- dtool/src/cppparser/cppToken.h | 51 - dtool/src/cppparser/cppType.cxx | 535 - dtool/src/cppparser/cppType.h | 115 - dtool/src/cppparser/cppTypeDeclaration.cxx | 67 - dtool/src/cppparser/cppTypeDeclaration.h | 41 - dtool/src/cppparser/cppTypeParser.cxx | 77 - dtool/src/cppparser/cppTypeParser.h | 48 - dtool/src/cppparser/cppTypeProxy.cxx | 319 - dtool/src/cppparser/cppTypeProxy.h | 71 - dtool/src/cppparser/cppTypedefType.cxx | 471 - dtool/src/cppparser/cppTypedefType.h | 92 - dtool/src/cppparser/cppUsing.cxx | 53 - dtool/src/cppparser/cppUsing.h | 41 - dtool/src/cppparser/cppVisibility.cxx | 36 - dtool/src/cppparser/cppVisibility.h | 29 - .../src/cppparser/p3cppParser_composite1.cxx | 26 - .../src/cppparser/p3cppParser_composite2.cxx | 17 - dtool/src/interrogate/CMakeLists.txt | 128 - dtool/src/interrogate/README.md | 28 - dtool/src/interrogate/functionRemap.cxx | 1030 -- dtool/src/interrogate/functionRemap.h | 150 - dtool/src/interrogate/functionWriter.cxx | 76 - dtool/src/interrogate/functionWriter.h | 39 - .../functionWriterPtrFromPython.cxx | 100 - .../interrogate/functionWriterPtrFromPython.h | 41 - .../interrogate/functionWriterPtrToPython.cxx | 80 - .../interrogate/functionWriterPtrToPython.h | 39 - dtool/src/interrogate/functionWriters.cxx | 76 - dtool/src/interrogate/functionWriters.h | 49 - dtool/src/interrogate/interfaceMaker.cxx | 968 -- dtool/src/interrogate/interfaceMaker.h | 215 - dtool/src/interrogate/interfaceMakerC.cxx | 253 - dtool/src/interrogate/interfaceMakerC.h | 57 - .../src/interrogate/interfaceMakerPython.cxx | 71 - dtool/src/interrogate/interfaceMakerPython.h | 39 - .../interfaceMakerPythonNative.cxx | 8739 -------------- .../interrogate/interfaceMakerPythonNative.h | 232 - .../interrogate/interfaceMakerPythonObj.cxx | 658 - .../src/interrogate/interfaceMakerPythonObj.h | 70 - .../interfaceMakerPythonSimple.cxx | 535 - .../interrogate/interfaceMakerPythonSimple.h | 64 - dtool/src/interrogate/interrogate.cxx | 638 - dtool/src/interrogate/interrogate.h | 50 - dtool/src/interrogate/interrogateBuilder.cxx | 3214 ----- dtool/src/interrogate/interrogateBuilder.h | 167 - .../interrogate/interrogate_composite1.cxx | 14 - .../interrogate/interrogate_composite2.cxx | 19 - dtool/src/interrogate/interrogate_module.cxx | 621 - dtool/src/interrogate/parameterRemap.I | 89 - dtool/src/interrogate/parameterRemap.cxx | 118 - dtool/src/interrogate/parameterRemap.h | 72 - .../parameterRemapBasicStringPtrToString.cxx | 83 - .../parameterRemapBasicStringPtrToString.h | 43 - .../parameterRemapBasicStringRefToString.cxx | 83 - .../parameterRemapBasicStringRefToString.h | 43 - .../parameterRemapBasicStringToString.cxx | 111 - .../parameterRemapBasicStringToString.h | 47 - .../parameterRemapCharStarToString.cxx | 32 - .../parameterRemapCharStarToString.h | 37 - .../parameterRemapConcreteToPointer.cxx | 91 - .../parameterRemapConcreteToPointer.h | 36 - .../parameterRemapConstToNonConst.cxx | 45 - .../parameterRemapConstToNonConst.h | 34 - .../interrogate/parameterRemapEnumToInt.cxx | 70 - .../src/interrogate/parameterRemapEnumToInt.h | 38 - .../interrogate/parameterRemapHandleToInt.cxx | 56 - .../interrogate/parameterRemapHandleToInt.h | 37 - .../interrogate/parameterRemapPTToPointer.cxx | 92 - .../interrogate/parameterRemapPTToPointer.h | 40 - .../parameterRemapReferenceToConcrete.cxx | 49 - .../parameterRemapReferenceToConcrete.h | 34 - .../parameterRemapReferenceToPointer.cxx | 58 - .../parameterRemapReferenceToPointer.h | 33 - dtool/src/interrogate/parameterRemapThis.cxx | 61 - dtool/src/interrogate/parameterRemapThis.h | 35 - .../interrogate/parameterRemapToString.cxx | 115 - .../src/interrogate/parameterRemapToString.h | 57 - .../interrogate/parameterRemapUnchanged.cxx | 23 - .../src/interrogate/parameterRemapUnchanged.h | 30 - dtool/src/interrogate/parse_file.cxx | 379 - dtool/src/interrogate/typeManager.cxx | 2614 ---- dtool/src/interrogate/typeManager.h | 157 - .../src/test_interrogate/test_interrogate.cxx | 615 - dtool/src/test_interrogate/test_lib.cxx | 40 - dtool/src/test_interrogate/test_lib.h | 35 - 159 files changed, 61522 deletions(-) delete mode 100644 dtool/src/cppparser/CMakeLists.txt delete mode 100644 dtool/src/cppparser/cppArrayType.cxx delete mode 100644 dtool/src/cppparser/cppArrayType.h delete mode 100644 dtool/src/cppparser/cppAttributeList.cxx delete mode 100644 dtool/src/cppparser/cppAttributeList.h delete mode 100644 dtool/src/cppparser/cppBison.cxx.prebuilt delete mode 100644 dtool/src/cppparser/cppBison.h.prebuilt delete mode 100644 dtool/src/cppparser/cppBison.yxx delete mode 100644 dtool/src/cppparser/cppBisonDefs.h delete mode 100644 dtool/src/cppparser/cppClassTemplateParameter.cxx delete mode 100644 dtool/src/cppparser/cppClassTemplateParameter.h delete mode 100644 dtool/src/cppparser/cppClosureType.cxx delete mode 100644 dtool/src/cppparser/cppClosureType.h delete mode 100644 dtool/src/cppparser/cppCommentBlock.cxx delete mode 100644 dtool/src/cppparser/cppCommentBlock.h delete mode 100644 dtool/src/cppparser/cppConstType.cxx delete mode 100644 dtool/src/cppparser/cppConstType.h delete mode 100644 dtool/src/cppparser/cppDeclaration.cxx delete mode 100644 dtool/src/cppparser/cppDeclaration.h delete mode 100644 dtool/src/cppparser/cppEnumType.cxx delete mode 100644 dtool/src/cppparser/cppEnumType.h delete mode 100644 dtool/src/cppparser/cppExpression.cxx delete mode 100644 dtool/src/cppparser/cppExpression.h delete mode 100644 dtool/src/cppparser/cppExpressionParser.cxx delete mode 100644 dtool/src/cppparser/cppExpressionParser.h delete mode 100644 dtool/src/cppparser/cppExtensionType.cxx delete mode 100644 dtool/src/cppparser/cppExtensionType.h delete mode 100644 dtool/src/cppparser/cppFile.cxx delete mode 100644 dtool/src/cppparser/cppFile.h delete mode 100644 dtool/src/cppparser/cppFunctionGroup.cxx delete mode 100644 dtool/src/cppparser/cppFunctionGroup.h delete mode 100644 dtool/src/cppparser/cppFunctionType.cxx delete mode 100644 dtool/src/cppparser/cppFunctionType.h delete mode 100644 dtool/src/cppparser/cppGlobals.cxx delete mode 100644 dtool/src/cppparser/cppGlobals.h delete mode 100644 dtool/src/cppparser/cppIdentifier.cxx delete mode 100644 dtool/src/cppparser/cppIdentifier.h delete mode 100644 dtool/src/cppparser/cppInstance.cxx delete mode 100644 dtool/src/cppparser/cppInstance.h delete mode 100644 dtool/src/cppparser/cppInstanceIdentifier.cxx delete mode 100644 dtool/src/cppparser/cppInstanceIdentifier.h delete mode 100644 dtool/src/cppparser/cppMakeProperty.cxx delete mode 100644 dtool/src/cppparser/cppMakeProperty.h delete mode 100644 dtool/src/cppparser/cppMakeSeq.cxx delete mode 100644 dtool/src/cppparser/cppMakeSeq.h delete mode 100644 dtool/src/cppparser/cppManifest.cxx delete mode 100644 dtool/src/cppparser/cppManifest.h delete mode 100644 dtool/src/cppparser/cppNameComponent.cxx delete mode 100644 dtool/src/cppparser/cppNameComponent.h delete mode 100644 dtool/src/cppparser/cppNamespace.cxx delete mode 100644 dtool/src/cppparser/cppNamespace.h delete mode 100644 dtool/src/cppparser/cppParameterList.cxx delete mode 100644 dtool/src/cppparser/cppParameterList.h delete mode 100644 dtool/src/cppparser/cppParser.cxx delete mode 100644 dtool/src/cppparser/cppParser.h delete mode 100644 dtool/src/cppparser/cppPointerType.cxx delete mode 100644 dtool/src/cppparser/cppPointerType.h delete mode 100644 dtool/src/cppparser/cppPreprocessor.cxx delete mode 100644 dtool/src/cppparser/cppPreprocessor.h delete mode 100644 dtool/src/cppparser/cppReferenceType.cxx delete mode 100644 dtool/src/cppparser/cppReferenceType.h delete mode 100644 dtool/src/cppparser/cppScope.cxx delete mode 100644 dtool/src/cppparser/cppScope.h delete mode 100644 dtool/src/cppparser/cppSimpleType.cxx delete mode 100644 dtool/src/cppparser/cppSimpleType.h delete mode 100644 dtool/src/cppparser/cppStructType.cxx delete mode 100644 dtool/src/cppparser/cppStructType.h delete mode 100644 dtool/src/cppparser/cppTBDType.cxx delete mode 100644 dtool/src/cppparser/cppTBDType.h delete mode 100644 dtool/src/cppparser/cppTemplateParameterList.cxx delete mode 100644 dtool/src/cppparser/cppTemplateParameterList.h delete mode 100644 dtool/src/cppparser/cppTemplateScope.cxx delete mode 100644 dtool/src/cppparser/cppTemplateScope.h delete mode 100644 dtool/src/cppparser/cppToken.cxx delete mode 100644 dtool/src/cppparser/cppToken.h delete mode 100644 dtool/src/cppparser/cppType.cxx delete mode 100644 dtool/src/cppparser/cppType.h delete mode 100644 dtool/src/cppparser/cppTypeDeclaration.cxx delete mode 100644 dtool/src/cppparser/cppTypeDeclaration.h delete mode 100644 dtool/src/cppparser/cppTypeParser.cxx delete mode 100644 dtool/src/cppparser/cppTypeParser.h delete mode 100644 dtool/src/cppparser/cppTypeProxy.cxx delete mode 100644 dtool/src/cppparser/cppTypeProxy.h delete mode 100644 dtool/src/cppparser/cppTypedefType.cxx delete mode 100644 dtool/src/cppparser/cppTypedefType.h delete mode 100644 dtool/src/cppparser/cppUsing.cxx delete mode 100644 dtool/src/cppparser/cppUsing.h delete mode 100644 dtool/src/cppparser/cppVisibility.cxx delete mode 100644 dtool/src/cppparser/cppVisibility.h delete mode 100644 dtool/src/cppparser/p3cppParser_composite1.cxx delete mode 100644 dtool/src/cppparser/p3cppParser_composite2.cxx delete mode 100644 dtool/src/interrogate/CMakeLists.txt delete mode 100644 dtool/src/interrogate/README.md delete mode 100644 dtool/src/interrogate/functionRemap.cxx delete mode 100644 dtool/src/interrogate/functionRemap.h delete mode 100644 dtool/src/interrogate/functionWriter.cxx delete mode 100644 dtool/src/interrogate/functionWriter.h delete mode 100644 dtool/src/interrogate/functionWriterPtrFromPython.cxx delete mode 100644 dtool/src/interrogate/functionWriterPtrFromPython.h delete mode 100644 dtool/src/interrogate/functionWriterPtrToPython.cxx delete mode 100644 dtool/src/interrogate/functionWriterPtrToPython.h delete mode 100644 dtool/src/interrogate/functionWriters.cxx delete mode 100644 dtool/src/interrogate/functionWriters.h delete mode 100644 dtool/src/interrogate/interfaceMaker.cxx delete mode 100644 dtool/src/interrogate/interfaceMaker.h delete mode 100644 dtool/src/interrogate/interfaceMakerC.cxx delete mode 100644 dtool/src/interrogate/interfaceMakerC.h delete mode 100644 dtool/src/interrogate/interfaceMakerPython.cxx delete mode 100644 dtool/src/interrogate/interfaceMakerPython.h delete mode 100644 dtool/src/interrogate/interfaceMakerPythonNative.cxx delete mode 100644 dtool/src/interrogate/interfaceMakerPythonNative.h delete mode 100644 dtool/src/interrogate/interfaceMakerPythonObj.cxx delete mode 100644 dtool/src/interrogate/interfaceMakerPythonObj.h delete mode 100644 dtool/src/interrogate/interfaceMakerPythonSimple.cxx delete mode 100644 dtool/src/interrogate/interfaceMakerPythonSimple.h delete mode 100644 dtool/src/interrogate/interrogate.cxx delete mode 100644 dtool/src/interrogate/interrogate.h delete mode 100644 dtool/src/interrogate/interrogateBuilder.cxx delete mode 100644 dtool/src/interrogate/interrogateBuilder.h delete mode 100644 dtool/src/interrogate/interrogate_composite1.cxx delete mode 100644 dtool/src/interrogate/interrogate_composite2.cxx delete mode 100644 dtool/src/interrogate/interrogate_module.cxx delete mode 100644 dtool/src/interrogate/parameterRemap.I delete mode 100644 dtool/src/interrogate/parameterRemap.cxx delete mode 100644 dtool/src/interrogate/parameterRemap.h delete mode 100644 dtool/src/interrogate/parameterRemapBasicStringPtrToString.cxx delete mode 100644 dtool/src/interrogate/parameterRemapBasicStringPtrToString.h delete mode 100644 dtool/src/interrogate/parameterRemapBasicStringRefToString.cxx delete mode 100644 dtool/src/interrogate/parameterRemapBasicStringRefToString.h delete mode 100644 dtool/src/interrogate/parameterRemapBasicStringToString.cxx delete mode 100644 dtool/src/interrogate/parameterRemapBasicStringToString.h delete mode 100644 dtool/src/interrogate/parameterRemapCharStarToString.cxx delete mode 100644 dtool/src/interrogate/parameterRemapCharStarToString.h delete mode 100644 dtool/src/interrogate/parameterRemapConcreteToPointer.cxx delete mode 100644 dtool/src/interrogate/parameterRemapConcreteToPointer.h delete mode 100644 dtool/src/interrogate/parameterRemapConstToNonConst.cxx delete mode 100644 dtool/src/interrogate/parameterRemapConstToNonConst.h delete mode 100644 dtool/src/interrogate/parameterRemapEnumToInt.cxx delete mode 100644 dtool/src/interrogate/parameterRemapEnumToInt.h delete mode 100644 dtool/src/interrogate/parameterRemapHandleToInt.cxx delete mode 100644 dtool/src/interrogate/parameterRemapHandleToInt.h delete mode 100644 dtool/src/interrogate/parameterRemapPTToPointer.cxx delete mode 100644 dtool/src/interrogate/parameterRemapPTToPointer.h delete mode 100644 dtool/src/interrogate/parameterRemapReferenceToConcrete.cxx delete mode 100644 dtool/src/interrogate/parameterRemapReferenceToConcrete.h delete mode 100644 dtool/src/interrogate/parameterRemapReferenceToPointer.cxx delete mode 100644 dtool/src/interrogate/parameterRemapReferenceToPointer.h delete mode 100644 dtool/src/interrogate/parameterRemapThis.cxx delete mode 100644 dtool/src/interrogate/parameterRemapThis.h delete mode 100644 dtool/src/interrogate/parameterRemapToString.cxx delete mode 100644 dtool/src/interrogate/parameterRemapToString.h delete mode 100644 dtool/src/interrogate/parameterRemapUnchanged.cxx delete mode 100644 dtool/src/interrogate/parameterRemapUnchanged.h delete mode 100644 dtool/src/interrogate/parse_file.cxx delete mode 100644 dtool/src/interrogate/typeManager.cxx delete mode 100644 dtool/src/interrogate/typeManager.h delete mode 100644 dtool/src/test_interrogate/test_interrogate.cxx delete mode 100644 dtool/src/test_interrogate/test_lib.cxx delete mode 100644 dtool/src/test_interrogate/test_lib.h diff --git a/dtool/src/cppparser/CMakeLists.txt b/dtool/src/cppparser/CMakeLists.txt deleted file mode 100644 index 08563df508..0000000000 --- a/dtool/src/cppparser/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -set(P3CPPPARSER_HEADERS - cppAttributeList.h - cppArrayType.h cppBison.yxx cppBisonDefs.h - cppClassTemplateParameter.h cppCommentBlock.h - cppClosureType.h cppConstType.h - cppDeclaration.h cppEnumType.h cppExpression.h - cppExpressionParser.h cppExtensionType.h cppFile.h - cppFunctionGroup.h cppFunctionType.h cppGlobals.h - cppIdentifier.h cppInstance.h cppInstanceIdentifier.h - cppMakeProperty.h cppMakeSeq.h cppManifest.h - cppNameComponent.h cppNamespace.h - cppParameterList.h cppParser.h cppPointerType.h - cppPreprocessor.h cppReferenceType.h cppScope.h - cppSimpleType.h cppStructType.h cppTBDType.h - cppTemplateParameterList.h cppTemplateScope.h cppToken.h - cppType.h cppTypeDeclaration.h cppTypeParser.h - cppTypeProxy.h cppTypedefType.h cppUsing.h cppVisibility.h -) - -set(P3CPPPARSER_SOURCES - cppAttributeList.cxx - cppArrayType.cxx ${CMAKE_CURRENT_BINARY_DIR}/cppBison.cxx - cppClassTemplateParameter.cxx - cppCommentBlock.cxx cppClosureType.cxx cppConstType.cxx cppDeclaration.cxx - cppEnumType.cxx cppExpression.cxx cppExpressionParser.cxx - cppExtensionType.cxx cppFile.cxx cppFunctionGroup.cxx - cppFunctionType.cxx cppGlobals.cxx cppIdentifier.cxx - cppInstance.cxx cppInstanceIdentifier.cxx - cppMakeProperty.cxx cppMakeSeq.cxx cppManifest.cxx - cppNameComponent.cxx cppNamespace.cxx cppParameterList.cxx - cppParser.cxx cppPointerType.cxx cppPreprocessor.cxx - cppReferenceType.cxx cppScope.cxx cppSimpleType.cxx - cppStructType.cxx cppTBDType.cxx - cppTemplateParameterList.cxx cppTemplateScope.cxx - cppToken.cxx cppType.cxx cppTypeDeclaration.cxx - cppTypeParser.cxx cppTypeProxy.cxx cppTypedefType.cxx - cppUsing.cxx cppVisibility.cxx -) - -add_bison_target(cppBison.cxx cppBison.yxx DEFINES cppBison.h PREFIX cppyy) - -composite_sources(p3cppParser P3CPPPARSER_SOURCES) -add_library(p3cppParser STATIC ${P3CPPPARSER_HEADERS} ${P3CPPPARSER_SOURCES}) -target_link_libraries(p3cppParser p3dtool) - -install(TARGETS p3cppParser EXPORT Core COMPONENT CoreDevel DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/dtool/src/cppparser/cppArrayType.cxx b/dtool/src/cppparser/cppArrayType.cxx deleted file mode 100644 index efd06f17b6..0000000000 --- a/dtool/src/cppparser/cppArrayType.cxx +++ /dev/null @@ -1,269 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppArrayType.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppArrayType.h" -#include "cppExpression.h" -#include "cppPointerType.h" - -/** - * - */ -CPPArrayType:: -CPPArrayType(CPPType *element_type, CPPExpression *bounds) : - CPPType(CPPFile()), - _element_type(element_type), - _bounds(bounds) -{ -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPArrayType:: -is_fully_specified() const { - return CPPType::is_fully_specified() && - _element_type->is_fully_specified(); -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPArrayType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *ptype = _element_type->resolve_type(current_scope, global_scope); - - if (ptype != _element_type) { - CPPArrayType *rep = new CPPArrayType(*this); - rep->_element_type = ptype; - return CPPType::new_type(rep); - } - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPArrayType:: -is_tbd() const { - return _element_type->is_tbd(); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPArrayType:: -is_standard_layout() const { - return _element_type->is_standard_layout(); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPArrayType:: -is_trivial() const { - return _element_type->is_trivial(); -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPArrayType:: -is_trivially_copyable() const { - return _element_type->is_trivially_copyable(); -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPArrayType:: -is_default_constructible() const { - return _bounds != nullptr && _element_type->is_default_constructible(); -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPArrayType:: -is_copy_constructible() const { - // This is technically not exactly true, but array data members do not - // prevent C++ implicit copy constructor generation rules, so we need to - // return true here. - // If this is a problem, we will need to create a separate method for the - // purpose of checking copyability as a data member. - return true; -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPArrayType:: -is_copy_assignable() const { - // Same story as is_copy_constructible. - return true; -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPArrayType:: -is_equivalent(const CPPType &other) const { - const CPPArrayType *ot = ((CPPType *)&other)->as_array_type(); - if (ot == nullptr) { - return CPPType::is_equivalent(other); - } - - return _element_type->is_equivalent(*ot->_element_type); -} - -/** - * - */ -CPPDeclaration *CPPArrayType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPArrayType *rep = new CPPArrayType(*this); - rep->_element_type = - _element_type->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - - if (_bounds != nullptr) { - rep->_bounds = - _bounds->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - } - - if (rep->_element_type == _element_type && - rep->_bounds == _bounds) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_array_type(); - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * - */ -void CPPArrayType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - /* - _element_type->output(out, indent_level, scope, complete); - out << "["; - if (_bounds != NULL) { - out << *_bounds; - } - out << "]"; - */ - output_instance(out, indent_level, scope, complete, "", ""); -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPArrayType:: -output_instance(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const { - std::ostringstream brackets; - brackets << "["; - if (_bounds != nullptr) { - brackets << *_bounds; - } - brackets << "]"; - - if (!_attributes.is_empty()) { - brackets << " " << _attributes; - } - - std::string bracketsstr = brackets.str(); - - _element_type->output_instance(out, indent_level, scope, complete, - prename, name + bracketsstr); -} - -/** - * - */ -CPPDeclaration::SubType CPPArrayType:: -get_subtype() const { - return ST_array; -} - -/** - * - */ -CPPArrayType *CPPArrayType:: -as_array_type() { - return this; -} - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPArrayType:: -is_equal(const CPPDeclaration *other) const { - const CPPArrayType *ot = ((CPPDeclaration *)other)->as_array_type(); - assert(ot != nullptr); - - if (_bounds != nullptr && ot->_bounds != nullptr) { - if (*_bounds != *ot->_bounds) { - return false; - } - } else if ((_bounds == nullptr) != (ot->_bounds == nullptr)) { - return false; - } - - return *_element_type == *ot->_element_type; -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPArrayType:: -is_less(const CPPDeclaration *other) const { - const CPPArrayType *ot = ((CPPDeclaration *)other)->as_array_type(); - assert(ot != nullptr); - - if (_bounds != nullptr && ot->_bounds != nullptr) { - if (*_bounds != *ot->_bounds) { - return *_bounds < *ot->_bounds; - } - } else if ((_bounds == nullptr) != (ot->_bounds == nullptr)) { - return _bounds < ot->_bounds; - } - - if (*_element_type != *ot->_element_type) { - return *_element_type < *ot->_element_type; - } - return false; -} diff --git a/dtool/src/cppparser/cppArrayType.h b/dtool/src/cppparser/cppArrayType.h deleted file mode 100644 index 56afed1cbf..0000000000 --- a/dtool/src/cppparser/cppArrayType.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppArrayType.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPARRAYTYPE_H -#define CPPARRAYTYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -class CPPExpression; - -/** - * - */ -class CPPArrayType : public CPPType { -public: - CPPArrayType(CPPType *element_type, CPPExpression *bounds); - - CPPType *_element_type; - CPPExpression *_bounds; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - virtual bool is_tbd() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - virtual bool is_equivalent(const CPPType &other) const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - - virtual SubType get_subtype() const; - - virtual CPPArrayType *as_array_type(); - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppAttributeList.cxx b/dtool/src/cppparser/cppAttributeList.cxx deleted file mode 100644 index 6a280d3cd7..0000000000 --- a/dtool/src/cppparser/cppAttributeList.cxx +++ /dev/null @@ -1,196 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppAttributeList.cxx - * @author rdb - * @date 2022-10-23 - */ - -#include "cppAttributeList.h" -#include "cppExpression.h" -#include "cppIdentifier.h" -#include "cppType.h" - -/** - * Returns true if no attributes have been defined. - */ -bool CPPAttributeList:: -is_empty() const { - return _attributes.empty() && _alignas == nullptr; -} - -/** - * Returns true if the attribute list has an attribute with the given name. - */ -bool CPPAttributeList:: -has_attribute(const std::string &name) const { - for (const Attribute &attr : _attributes) { - if (attr._ident->get_fully_scoped_name() == name) { - return true; - } - } - return false; -} - -/** - * - */ -bool CPPAttributeList:: -operator == (const CPPAttributeList &other) const { - if (_attributes.size() != other._attributes.size()) { - return false; - } - if ((_alignas != nullptr) != (other._alignas != nullptr)) { - return false; - } - if (_alignas != nullptr && *_alignas != *other._alignas) { - return false; - } - for (size_t i = 0; i < _attributes.size(); ++i) { - if (_attributes[i]._ident != other._attributes[i]._ident) { - return false; - } - if (_attributes[i]._reason != other._attributes[i]._reason) { - return false; - } - } - return true; -} - -/** - * - */ -bool CPPAttributeList:: -operator != (const CPPAttributeList &other) const { - return !(*this == other); -} - -/** - * - */ -bool CPPAttributeList:: -operator < (const CPPAttributeList &other) const { - if (_attributes.size() != other._attributes.size()) { - return _attributes.size() < other._attributes.size(); - } - if ((_alignas != nullptr) != (other._alignas != nullptr)) { - return _alignas == nullptr; - } - if (_alignas != nullptr && *_alignas != *other._alignas) { - return *_alignas < *other._alignas; - } - for (size_t i = 0; i < _attributes.size(); ++i) { - if (_attributes[i]._ident != other._attributes[i]._ident) { - return _attributes[i]._ident < other._attributes[i]._ident; - } - if (_attributes[i]._reason != other._attributes[i]._reason) { - return _attributes[i]._reason < other._attributes[i]._reason; - } - } - return false; -} - -/** - * Adds an attribute. - */ -void CPPAttributeList:: -add_attribute(CPPIdentifier *ident) { - _attributes.push_back({ident}); -} - -/** - * Adds an attribute. - */ -void CPPAttributeList:: -add_attribute(CPPIdentifier *ident, std::string reason) { - _attributes.push_back({ident, std::move(reason)}); -} - -/** - * Adds an alignas specifier. - */ -void CPPAttributeList:: -add_alignas(int size) { - if (_alignas == nullptr || size >= _alignas->evaluate().as_integer()) { - _alignas = new CPPExpression(size); - } -} - -/** - * Adds an alignas specifier. - */ -void CPPAttributeList:: -add_alignas(CPPType *type) { - CPPExpression expr = CPPExpression::alignof_func(type); - if (_alignas == nullptr || expr.evaluate().as_integer() > _alignas->evaluate().as_integer()) { - _alignas = new CPPExpression(expr); - } -} - -/** - * Adds an alignas specifier. - */ -void CPPAttributeList:: -add_alignas(CPPExpression *expr) { - if (_alignas == nullptr || expr->evaluate().as_integer() > _alignas->evaluate().as_integer()) { - _alignas = expr; - } -} - -/** - * Merges the other list into this one. - */ -void CPPAttributeList:: -add_attributes_from(const CPPAttributeList &other) { - for (const Attribute &attr : other._attributes) { - _attributes.push_back(attr); - } - - if (other._alignas != nullptr) { - add_alignas(other._alignas); - } -} - -/** - * - */ -void CPPAttributeList:: -output(std::ostream &out, CPPScope *scope) const { - Attributes::const_iterator it = _attributes.begin(); - if (it != _attributes.end()) { - out << "[["; - (*it)._ident->output(out, scope); - if (!(*it)._reason.empty()) { - out << "(" << (*it)._reason << ")"; - } - - for (++it; it != _attributes.end(); ++it) { - out << ", "; - (*it)._ident->output(out, scope); - if (!(*it)._reason.empty()) { - out << "(" << (*it)._reason << ")"; - } - } - - out << "]]"; - - if (_alignas != nullptr) { - out << " "; - } - } - - if (_alignas != nullptr) { - out << "alignas("; - if (_alignas->_type == CPPExpression::T_alignof) { - _alignas->_u._typecast._to->output(out, 0, scope, false); - } else { - _alignas->output(out, 0, scope, false); - } - out << ")"; - } -} diff --git a/dtool/src/cppparser/cppAttributeList.h b/dtool/src/cppparser/cppAttributeList.h deleted file mode 100644 index 9463b2b65c..0000000000 --- a/dtool/src/cppparser/cppAttributeList.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppAttributeList.h - * @author rdb - * @date 2022-10-23 - */ - -#ifndef CPPATTRIBUTELIST_H -#define CPPATTRIBUTELIST_H - -#include "dtoolbase.h" - -#include - -class CPPExpression; -class CPPIdentifier; -class CPPScope; -class CPPType; - -/** - * A list of square-bracket attributes and/or alignas specifiers. - */ -class CPPAttributeList { -public: - bool is_empty() const; - bool has_attribute(const std::string &name) const; - - bool operator == (const CPPAttributeList &other) const; - bool operator != (const CPPAttributeList &other) const; - bool operator < (const CPPAttributeList &other) const; - - void add_attribute(CPPIdentifier *ident); - void add_attribute(CPPIdentifier *ident, std::string reason); - - void add_alignas(int size); - void add_alignas(CPPType *type); - void add_alignas(CPPExpression *expr); - - void add_attributes_from(const CPPAttributeList &other); - - struct Attribute { - CPPIdentifier *_ident; - std::string _reason; - }; - - typedef std::vector Attributes; - Attributes _attributes; - CPPExpression *_alignas = nullptr; - - void output(std::ostream &out, CPPScope *scope) const; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPAttributeList &alist) { - alist.output(out, nullptr); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppBison.cxx.prebuilt b/dtool/src/cppparser/cppBison.cxx.prebuilt deleted file mode 100644 index 0d94f44c79..0000000000 --- a/dtool/src/cppparser/cppBison.cxx.prebuilt +++ /dev/null @@ -1,10080 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.8.2. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output, and Bison version. */ -#define YYBISON 30802 - -/* Bison version string. */ -#define YYBISON_VERSION "3.8.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 2 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - -/* Substitute the variable and function names. */ -#define yyparse cppyyparse -#define yylex cppyylex -#define yyerror cppyyerror -#define yydebug cppyydebug -#define yynerrs cppyynerrs - -/* First part of user prologue. */ -#line 7 "dtool/src/cppparser/cppBison.yxx" - - -#include "cppBisonDefs.h" -#include "cppParser.h" -#include "cppClosureType.h" -#include "cppExpression.h" -#include "cppSimpleType.h" -#include "cppExtensionType.h" -#include "cppStructType.h" -#include "cppEnumType.h" -#include "cppFunctionType.h" -#include "cppTBDType.h" -#include "cppMakeProperty.h" -#include "cppMakeSeq.h" -#include "cppParameterList.h" -#include "cppInstance.h" -#include "cppClassTemplateParameter.h" -#include "cppTemplateParameterList.h" -#include "cppInstanceIdentifier.h" -#include "cppTypedefType.h" -#include "cppTypeDeclaration.h" -#include "cppVisibility.h" -#include "cppIdentifier.h" -#include "cppScope.h" -#include "cppTemplateScope.h" -#include "cppNamespace.h" -#include "cppUsing.h" - -using std::stringstream; -using std::string; - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the parser. -//////////////////////////////////////////////////////////////////// - -CPPScope *current_scope = nullptr; -CPPScope *global_scope = nullptr; -CPPPreprocessor *current_lexer = nullptr; - -static CPPStructType *current_struct = nullptr; -static CPPEnumType *current_enum = nullptr; -static int current_storage_class = 0; -static CPPType *current_type = nullptr; -static CPPExpression *current_expr = nullptr; -static CPPAttributeList current_attributes; -static int publish_nest_level = 0; -static CPPVisibility publish_previous; -static YYLTYPE publish_loc; - -static std::vector last_scopes; -static std::vector last_storage_classes; -static std::vector last_structs; - -int yyparse(); - -#define YYERROR_VERBOSE - -static void -yyerror(const string &msg) { - current_lexer->error(msg, current_lexer->_last_token_loc); -} - -static void -yyerror(YYLTYPE *loc, const string &msg) { - current_lexer->error(msg, *loc); -} - -static void -yyerror(const string &msg, YYLTYPE &loc) { - current_lexer->error(msg, loc); -} - -static void -yywarning(const string &msg, YYLTYPE &loc) { - current_lexer->warning(msg, loc); -} - -static int -yylex(YYSTYPE *lval, YYLTYPE *lloc) { - CPPToken token = current_lexer->get_next_token(); - *lval = token._lval; - *lloc = token._lloc; - return token._token; -} - -void -parse_cpp(CPPParser *cp) { - CPPScope *old_scope = current_scope; - CPPScope *old_global_scope = global_scope; - CPPPreprocessor *old_lexer = current_lexer; - - current_scope = cp; - global_scope = cp; - current_lexer = cp; - publish_nest_level = 0; - yyparse(); - - if (publish_nest_level != 0) { - yyerror("Unclosed __begin_publish", publish_loc); - publish_nest_level = 0; - } - - current_scope = old_scope; - global_scope = old_global_scope; - current_lexer = old_lexer; - -} - -CPPExpression * -parse_const_expr(CPPPreprocessor *pp, CPPScope *new_current_scope, - CPPScope *new_global_scope) { - CPPScope *old_scope = current_scope; - CPPScope *old_global_scope = global_scope; - CPPPreprocessor *old_lexer = current_lexer; - CPPExpression *old_expr = current_expr; - - current_scope = new_current_scope; - global_scope = new_global_scope; - current_expr = nullptr; - current_lexer = pp; - yyparse(); - - CPPExpression *result = current_expr; - - current_scope = old_scope; - global_scope = old_global_scope; - current_lexer = old_lexer; - current_expr = old_expr; - - return result; -} - -CPPType * -parse_type(CPPPreprocessor *pp, CPPScope *new_current_scope, - CPPScope *new_global_scope) { - CPPScope *old_scope = current_scope; - CPPScope *old_global_scope = global_scope; - CPPPreprocessor *old_lexer = current_lexer; - CPPType *old_type = current_type; - - current_scope = new_current_scope; - global_scope = new_global_scope; - current_type = nullptr; - current_lexer = pp; - yyparse(); - - CPPType *result = current_type; - - current_scope = old_scope; - global_scope = old_global_scope; - current_lexer = old_lexer; - current_type = old_type; - - return result; -} - -static void -push_scope(CPPScope *new_scope) { - last_scopes.push_back(current_scope); - if (new_scope != nullptr) { - current_scope = new_scope; - } -} - -static void -pop_scope() { - assert(!last_scopes.empty()); - current_scope = last_scopes.back(); - last_scopes.pop_back(); -} - -static void -push_storage_class(int new_storage_class) { - last_storage_classes.push_back(current_storage_class); - current_storage_class = new_storage_class; -} - -static void -pop_storage_class() { - assert(!last_storage_classes.empty()); - current_storage_class = last_storage_classes.back(); - last_storage_classes.pop_back(); -} - -static void -push_struct(CPPStructType *new_struct) { - last_structs.push_back(current_struct); - current_struct = new_struct; -} - -static void -pop_struct() { - assert(!last_structs.empty()); - current_struct = last_structs.back(); - last_structs.pop_back(); -} - - -#line 275 "built/tmp/cppBison.yxx.c" - -# ifndef YY_CAST -# ifdef __cplusplus -# define YY_CAST(Type, Val) static_cast (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) -# else -# define YY_CAST(Type, Val) ((Type) (Val)) -# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) -# endif -# endif -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif - -#include "cppBison.yxx.h" -/* Symbol kind. */ -enum yysymbol_kind_t -{ - YYSYMBOL_YYEMPTY = -2, - YYSYMBOL_YYEOF = 0, /* "end of file" */ - YYSYMBOL_YYerror = 1, /* error */ - YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ - YYSYMBOL_REAL = 3, /* REAL */ - YYSYMBOL_INTEGER = 4, /* INTEGER */ - YYSYMBOL_CHAR_TOK = 5, /* CHAR_TOK */ - YYSYMBOL_SIMPLE_STRING = 6, /* SIMPLE_STRING */ - YYSYMBOL_SIMPLE_IDENTIFIER = 7, /* SIMPLE_IDENTIFIER */ - YYSYMBOL_STRING_LITERAL = 8, /* STRING_LITERAL */ - YYSYMBOL_CUSTOM_LITERAL = 9, /* CUSTOM_LITERAL */ - YYSYMBOL_IDENTIFIER = 10, /* IDENTIFIER */ - YYSYMBOL_TYPENAME_IDENTIFIER = 11, /* TYPENAME_IDENTIFIER */ - YYSYMBOL_TYPEPACK_IDENTIFIER = 12, /* TYPEPACK_IDENTIFIER */ - YYSYMBOL_SCOPING = 13, /* SCOPING */ - YYSYMBOL_TYPEDEFNAME = 14, /* TYPEDEFNAME */ - YYSYMBOL_ELLIPSIS = 15, /* ELLIPSIS */ - YYSYMBOL_OROR = 16, /* OROR */ - YYSYMBOL_ANDAND = 17, /* ANDAND */ - YYSYMBOL_EQCOMPARE = 18, /* EQCOMPARE */ - YYSYMBOL_NECOMPARE = 19, /* NECOMPARE */ - YYSYMBOL_LECOMPARE = 20, /* LECOMPARE */ - YYSYMBOL_GECOMPARE = 21, /* GECOMPARE */ - YYSYMBOL_SPACESHIP = 22, /* SPACESHIP */ - YYSYMBOL_LSHIFT = 23, /* LSHIFT */ - YYSYMBOL_RSHIFT = 24, /* RSHIFT */ - YYSYMBOL_POINTSAT_STAR = 25, /* POINTSAT_STAR */ - YYSYMBOL_DOT_STAR = 26, /* DOT_STAR */ - YYSYMBOL_UNARY = 27, /* UNARY */ - YYSYMBOL_UNARY_NOT = 28, /* UNARY_NOT */ - YYSYMBOL_UNARY_NEGATE = 29, /* UNARY_NEGATE */ - YYSYMBOL_UNARY_MINUS = 30, /* UNARY_MINUS */ - YYSYMBOL_UNARY_PLUS = 31, /* UNARY_PLUS */ - YYSYMBOL_UNARY_STAR = 32, /* UNARY_STAR */ - YYSYMBOL_UNARY_REF = 33, /* UNARY_REF */ - YYSYMBOL_POINTSAT = 34, /* POINTSAT */ - YYSYMBOL_SCOPE = 35, /* SCOPE */ - YYSYMBOL_PLUSPLUS = 36, /* PLUSPLUS */ - YYSYMBOL_MINUSMINUS = 37, /* MINUSMINUS */ - YYSYMBOL_TIMESEQUAL = 38, /* TIMESEQUAL */ - YYSYMBOL_DIVIDEEQUAL = 39, /* DIVIDEEQUAL */ - YYSYMBOL_MODEQUAL = 40, /* MODEQUAL */ - YYSYMBOL_PLUSEQUAL = 41, /* PLUSEQUAL */ - YYSYMBOL_MINUSEQUAL = 42, /* MINUSEQUAL */ - YYSYMBOL_OREQUAL = 43, /* OREQUAL */ - YYSYMBOL_ANDEQUAL = 44, /* ANDEQUAL */ - YYSYMBOL_XOREQUAL = 45, /* XOREQUAL */ - YYSYMBOL_LSHIFTEQUAL = 46, /* LSHIFTEQUAL */ - YYSYMBOL_RSHIFTEQUAL = 47, /* RSHIFTEQUAL */ - YYSYMBOL_ATTR_LEFT = 48, /* ATTR_LEFT */ - YYSYMBOL_ATTR_RIGHT = 49, /* ATTR_RIGHT */ - YYSYMBOL_KW_ALIGNAS = 50, /* KW_ALIGNAS */ - YYSYMBOL_KW_ALIGNOF = 51, /* KW_ALIGNOF */ - YYSYMBOL_KW_AUTO = 52, /* KW_AUTO */ - YYSYMBOL_KW_BEGIN_PUBLISH = 53, /* KW_BEGIN_PUBLISH */ - YYSYMBOL_KW_BLOCKING = 54, /* KW_BLOCKING */ - YYSYMBOL_KW_BOOL = 55, /* KW_BOOL */ - YYSYMBOL_KW_BUILTIN_VA_LIST = 56, /* KW_BUILTIN_VA_LIST */ - YYSYMBOL_KW_CATCH = 57, /* KW_CATCH */ - YYSYMBOL_KW_CHAR = 58, /* KW_CHAR */ - YYSYMBOL_KW_CHAR8_T = 59, /* KW_CHAR8_T */ - YYSYMBOL_KW_CHAR16_T = 60, /* KW_CHAR16_T */ - YYSYMBOL_KW_CHAR32_T = 61, /* KW_CHAR32_T */ - YYSYMBOL_KW_CLASS = 62, /* KW_CLASS */ - YYSYMBOL_KW_CONST = 63, /* KW_CONST */ - YYSYMBOL_KW_CONSTEVAL = 64, /* KW_CONSTEVAL */ - YYSYMBOL_KW_CONSTEXPR = 65, /* KW_CONSTEXPR */ - YYSYMBOL_KW_CONSTINIT = 66, /* KW_CONSTINIT */ - YYSYMBOL_KW_CONST_CAST = 67, /* KW_CONST_CAST */ - YYSYMBOL_KW_DECLTYPE = 68, /* KW_DECLTYPE */ - YYSYMBOL_KW_DEFAULT = 69, /* KW_DEFAULT */ - YYSYMBOL_KW_DELETE = 70, /* KW_DELETE */ - YYSYMBOL_KW_DOUBLE = 71, /* KW_DOUBLE */ - YYSYMBOL_KW_DYNAMIC_CAST = 72, /* KW_DYNAMIC_CAST */ - YYSYMBOL_KW_ELSE = 73, /* KW_ELSE */ - YYSYMBOL_KW_END_PUBLISH = 74, /* KW_END_PUBLISH */ - YYSYMBOL_KW_ENUM = 75, /* KW_ENUM */ - YYSYMBOL_KW_EXTENSION = 76, /* KW_EXTENSION */ - YYSYMBOL_KW_EXTERN = 77, /* KW_EXTERN */ - YYSYMBOL_KW_EXPLICIT = 78, /* KW_EXPLICIT */ - YYSYMBOL_KW_EXPLICIT_LPAREN = 79, /* KW_EXPLICIT_LPAREN */ - YYSYMBOL_KW_PUBLISHED = 80, /* KW_PUBLISHED */ - YYSYMBOL_KW_FALSE = 81, /* KW_FALSE */ - YYSYMBOL_KW_FINAL = 82, /* KW_FINAL */ - YYSYMBOL_KW_FLOAT = 83, /* KW_FLOAT */ - YYSYMBOL_KW_FRIEND = 84, /* KW_FRIEND */ - YYSYMBOL_KW_FOR = 85, /* KW_FOR */ - YYSYMBOL_KW_GOTO = 86, /* KW_GOTO */ - YYSYMBOL_KW_HAS_VIRTUAL_DESTRUCTOR = 87, /* KW_HAS_VIRTUAL_DESTRUCTOR */ - YYSYMBOL_KW_IF = 88, /* KW_IF */ - YYSYMBOL_KW_INLINE = 89, /* KW_INLINE */ - YYSYMBOL_KW_INT = 90, /* KW_INT */ - YYSYMBOL_KW_IS_ABSTRACT = 91, /* KW_IS_ABSTRACT */ - YYSYMBOL_KW_IS_BASE_OF = 92, /* KW_IS_BASE_OF */ - YYSYMBOL_KW_IS_CLASS = 93, /* KW_IS_CLASS */ - YYSYMBOL_KW_IS_CONSTRUCTIBLE = 94, /* KW_IS_CONSTRUCTIBLE */ - YYSYMBOL_KW_IS_CONVERTIBLE_TO = 95, /* KW_IS_CONVERTIBLE_TO */ - YYSYMBOL_KW_IS_DESTRUCTIBLE = 96, /* KW_IS_DESTRUCTIBLE */ - YYSYMBOL_KW_IS_EMPTY = 97, /* KW_IS_EMPTY */ - YYSYMBOL_KW_IS_ENUM = 98, /* KW_IS_ENUM */ - YYSYMBOL_KW_IS_FINAL = 99, /* KW_IS_FINAL */ - YYSYMBOL_KW_IS_FUNDAMENTAL = 100, /* KW_IS_FUNDAMENTAL */ - YYSYMBOL_KW_IS_POD = 101, /* KW_IS_POD */ - YYSYMBOL_KW_IS_POLYMORPHIC = 102, /* KW_IS_POLYMORPHIC */ - YYSYMBOL_KW_IS_STANDARD_LAYOUT = 103, /* KW_IS_STANDARD_LAYOUT */ - YYSYMBOL_KW_IS_TRIVIAL = 104, /* KW_IS_TRIVIAL */ - YYSYMBOL_KW_IS_TRIVIALLY_COPYABLE = 105, /* KW_IS_TRIVIALLY_COPYABLE */ - YYSYMBOL_KW_IS_UNION = 106, /* KW_IS_UNION */ - YYSYMBOL_KW_LONG = 107, /* KW_LONG */ - YYSYMBOL_KW_MAKE_MAP_KEYS_SEQ = 108, /* KW_MAKE_MAP_KEYS_SEQ */ - YYSYMBOL_KW_MAKE_MAP_PROPERTY = 109, /* KW_MAKE_MAP_PROPERTY */ - YYSYMBOL_KW_MAKE_PROPERTY = 110, /* KW_MAKE_PROPERTY */ - YYSYMBOL_KW_MAKE_PROPERTY2 = 111, /* KW_MAKE_PROPERTY2 */ - YYSYMBOL_KW_MAKE_SEQ = 112, /* KW_MAKE_SEQ */ - YYSYMBOL_KW_MAKE_SEQ_PROPERTY = 113, /* KW_MAKE_SEQ_PROPERTY */ - YYSYMBOL_KW_MUTABLE = 114, /* KW_MUTABLE */ - YYSYMBOL_KW_NAMESPACE = 115, /* KW_NAMESPACE */ - YYSYMBOL_KW_NEW = 116, /* KW_NEW */ - YYSYMBOL_KW_NOEXCEPT = 117, /* KW_NOEXCEPT */ - YYSYMBOL_KW_NOEXCEPT_LPAREN = 118, /* KW_NOEXCEPT_LPAREN */ - YYSYMBOL_KW_NULLPTR = 119, /* KW_NULLPTR */ - YYSYMBOL_KW_OPERATOR = 120, /* KW_OPERATOR */ - YYSYMBOL_KW_OVERRIDE = 121, /* KW_OVERRIDE */ - YYSYMBOL_KW_PRIVATE = 122, /* KW_PRIVATE */ - YYSYMBOL_KW_PROTECTED = 123, /* KW_PROTECTED */ - YYSYMBOL_KW_PUBLIC = 124, /* KW_PUBLIC */ - YYSYMBOL_KW_REGISTER = 125, /* KW_REGISTER */ - YYSYMBOL_KW_REINTERPRET_CAST = 126, /* KW_REINTERPRET_CAST */ - YYSYMBOL_KW_RESTRICT = 127, /* KW_RESTRICT */ - YYSYMBOL_KW_RETURN = 128, /* KW_RETURN */ - YYSYMBOL_KW_SHORT = 129, /* KW_SHORT */ - YYSYMBOL_KW_SIGNED = 130, /* KW_SIGNED */ - YYSYMBOL_KW_SIZEOF = 131, /* KW_SIZEOF */ - YYSYMBOL_KW_STATIC = 132, /* KW_STATIC */ - YYSYMBOL_KW_STATIC_ASSERT = 133, /* KW_STATIC_ASSERT */ - YYSYMBOL_KW_STATIC_CAST = 134, /* KW_STATIC_CAST */ - YYSYMBOL_KW_STRUCT = 135, /* KW_STRUCT */ - YYSYMBOL_KW_TEMPLATE = 136, /* KW_TEMPLATE */ - YYSYMBOL_KW_THREAD_LOCAL = 137, /* KW_THREAD_LOCAL */ - YYSYMBOL_KW_THROW = 138, /* KW_THROW */ - YYSYMBOL_KW_TRUE = 139, /* KW_TRUE */ - YYSYMBOL_KW_TRY = 140, /* KW_TRY */ - YYSYMBOL_KW_TYPEDEF = 141, /* KW_TYPEDEF */ - YYSYMBOL_KW_TYPEID = 142, /* KW_TYPEID */ - YYSYMBOL_KW_TYPENAME = 143, /* KW_TYPENAME */ - YYSYMBOL_KW_UNDERLYING_TYPE = 144, /* KW_UNDERLYING_TYPE */ - YYSYMBOL_KW_UNION = 145, /* KW_UNION */ - YYSYMBOL_KW_UNSIGNED = 146, /* KW_UNSIGNED */ - YYSYMBOL_KW_USING = 147, /* KW_USING */ - YYSYMBOL_KW_VIRTUAL = 148, /* KW_VIRTUAL */ - YYSYMBOL_KW_VOID = 149, /* KW_VOID */ - YYSYMBOL_KW_VOLATILE = 150, /* KW_VOLATILE */ - YYSYMBOL_KW_WCHAR_T = 151, /* KW_WCHAR_T */ - YYSYMBOL_KW_WHILE = 152, /* KW_WHILE */ - YYSYMBOL_START_CPP = 153, /* START_CPP */ - YYSYMBOL_START_CONST_EXPR = 154, /* START_CONST_EXPR */ - YYSYMBOL_START_TYPE = 155, /* START_TYPE */ - YYSYMBOL_156_ = 156, /* '{' */ - YYSYMBOL_157_ = 157, /* ',' */ - YYSYMBOL_158_ = 158, /* ';' */ - YYSYMBOL_159_ = 159, /* ':' */ - YYSYMBOL_160_ = 160, /* '=' */ - YYSYMBOL_161_ = 161, /* '?' */ - YYSYMBOL_162_ = 162, /* '|' */ - YYSYMBOL_163_ = 163, /* '^' */ - YYSYMBOL_164_ = 164, /* '&' */ - YYSYMBOL_165_ = 165, /* '<' */ - YYSYMBOL_166_ = 166, /* '>' */ - YYSYMBOL_167_ = 167, /* '+' */ - YYSYMBOL_168_ = 168, /* '-' */ - YYSYMBOL_169_ = 169, /* '*' */ - YYSYMBOL_170_ = 170, /* '/' */ - YYSYMBOL_171_ = 171, /* '%' */ - YYSYMBOL_172_ = 172, /* '~' */ - YYSYMBOL_173_ = 173, /* '.' */ - YYSYMBOL_174_ = 174, /* '(' */ - YYSYMBOL_175_ = 175, /* '[' */ - YYSYMBOL_176_ = 176, /* ')' */ - YYSYMBOL_177_ = 177, /* '}' */ - YYSYMBOL_178_ = 178, /* '!' */ - YYSYMBOL_179_ = 179, /* ']' */ - YYSYMBOL_YYACCEPT = 180, /* $accept */ - YYSYMBOL_grammar = 181, /* grammar */ - YYSYMBOL_cpp = 182, /* cpp */ - YYSYMBOL_183_1 = 183, /* $@1 */ - YYSYMBOL_constructor_inits = 184, /* constructor_inits */ - YYSYMBOL_constructor_init = 185, /* constructor_init */ - YYSYMBOL_extern_c = 186, /* extern_c */ - YYSYMBOL_187_2 = 187, /* $@2 */ - YYSYMBOL_declaration = 188, /* declaration */ - YYSYMBOL_friend_declaration = 189, /* friend_declaration */ - YYSYMBOL_190_3 = 190, /* $@3 */ - YYSYMBOL_storage_class = 191, /* storage_class */ - YYSYMBOL_optional_attributes = 192, /* optional_attributes */ - YYSYMBOL_attribute_specifiers = 193, /* attribute_specifiers */ - YYSYMBOL_attribute_specifier = 194, /* attribute_specifier */ - YYSYMBOL_type_like_declaration = 195, /* type_like_declaration */ - YYSYMBOL_196_4 = 196, /* $@4 */ - YYSYMBOL_197_5 = 197, /* $@5 */ - YYSYMBOL_multiple_instance_identifiers = 198, /* multiple_instance_identifiers */ - YYSYMBOL_typedef_declaration = 199, /* typedef_declaration */ - YYSYMBOL_200_6 = 200, /* $@6 */ - YYSYMBOL_typedef_instance_identifiers = 201, /* typedef_instance_identifiers */ - YYSYMBOL_constructor_prototype = 202, /* constructor_prototype */ - YYSYMBOL_203_7 = 203, /* $@7 */ - YYSYMBOL_204_8 = 204, /* $@8 */ - YYSYMBOL_205_9 = 205, /* $@9 */ - YYSYMBOL_function_prototype = 206, /* function_prototype */ - YYSYMBOL_207_10 = 207, /* $@10 */ - YYSYMBOL_208_11 = 208, /* $@11 */ - YYSYMBOL_209_12 = 209, /* $@12 */ - YYSYMBOL_210_13 = 210, /* $@13 */ - YYSYMBOL_211_14 = 211, /* $@14 */ - YYSYMBOL_function_post = 212, /* function_post */ - YYSYMBOL_function_operator = 213, /* function_operator */ - YYSYMBOL_more_template_declaration = 214, /* more_template_declaration */ - YYSYMBOL_template_declaration = 215, /* template_declaration */ - YYSYMBOL_216_15 = 216, /* $@15 */ - YYSYMBOL_template_formal_parameters = 217, /* template_formal_parameters */ - YYSYMBOL_template_nonempty_formal_parameters = 218, /* template_nonempty_formal_parameters */ - YYSYMBOL_typename_keyword = 219, /* typename_keyword */ - YYSYMBOL_template_formal_parameter = 220, /* template_formal_parameter */ - YYSYMBOL_template_formal_parameter_type = 221, /* template_formal_parameter_type */ - YYSYMBOL_instance_identifier = 222, /* instance_identifier */ - YYSYMBOL_223_16 = 223, /* $@16 */ - YYSYMBOL_instance_identifier_and_maybe_trailing_return_type = 224, /* instance_identifier_and_maybe_trailing_return_type */ - YYSYMBOL_maybe_trailing_return_type = 225, /* maybe_trailing_return_type */ - YYSYMBOL_maybe_comma_identifier = 226, /* maybe_comma_identifier */ - YYSYMBOL_function_parameter_list = 227, /* function_parameter_list */ - YYSYMBOL_function_parameters = 228, /* function_parameters */ - YYSYMBOL_formal_parameter_list = 229, /* formal_parameter_list */ - YYSYMBOL_formal_parameters = 230, /* formal_parameters */ - YYSYMBOL_template_parameter_maybe_initialize = 231, /* template_parameter_maybe_initialize */ - YYSYMBOL_maybe_initialize = 232, /* maybe_initialize */ - YYSYMBOL_maybe_initialize_or_constructor_body = 233, /* maybe_initialize_or_constructor_body */ - YYSYMBOL_maybe_initialize_or_function_body = 234, /* maybe_initialize_or_function_body */ - YYSYMBOL_structure_init = 235, /* structure_init */ - YYSYMBOL_structure_init_body = 236, /* structure_init_body */ - YYSYMBOL_function_parameter = 237, /* function_parameter */ - YYSYMBOL_formal_parameter = 238, /* formal_parameter */ - YYSYMBOL_not_paren_formal_parameter_identifier = 239, /* not_paren_formal_parameter_identifier */ - YYSYMBOL_formal_parameter_identifier = 240, /* formal_parameter_identifier */ - YYSYMBOL_parameter_pack_identifier = 241, /* parameter_pack_identifier */ - YYSYMBOL_not_paren_empty_instance_identifier = 242, /* not_paren_empty_instance_identifier */ - YYSYMBOL_empty_instance_identifier = 243, /* empty_instance_identifier */ - YYSYMBOL_type = 244, /* type */ - YYSYMBOL_type_pack = 245, /* type_pack */ - YYSYMBOL_type_decl = 246, /* type_decl */ - YYSYMBOL_predefined_type = 247, /* predefined_type */ - YYSYMBOL_var_type_decl = 248, /* var_type_decl */ - YYSYMBOL_full_type = 249, /* full_type */ - YYSYMBOL_anonymous_struct = 250, /* anonymous_struct */ - YYSYMBOL_251_17 = 251, /* $@17 */ - YYSYMBOL_named_struct = 252, /* named_struct */ - YYSYMBOL_253_18 = 253, /* $@18 */ - YYSYMBOL_maybe_final = 254, /* maybe_final */ - YYSYMBOL_maybe_class_derivation = 255, /* maybe_class_derivation */ - YYSYMBOL_class_derivation = 256, /* class_derivation */ - YYSYMBOL_base_specification = 257, /* base_specification */ - YYSYMBOL_enum = 258, /* enum */ - YYSYMBOL_259_19 = 259, /* $@19 */ - YYSYMBOL_enum_decl = 260, /* enum_decl */ - YYSYMBOL_enum_element_type = 261, /* enum_element_type */ - YYSYMBOL_enum_body_trailing_comma = 262, /* enum_body_trailing_comma */ - YYSYMBOL_enum_body = 263, /* enum_body */ - YYSYMBOL_enum_keyword = 264, /* enum_keyword */ - YYSYMBOL_struct_keyword = 265, /* struct_keyword */ - YYSYMBOL_namespace_declaration = 266, /* namespace_declaration */ - YYSYMBOL_267_20 = 267, /* $@20 */ - YYSYMBOL_268_21 = 268, /* $@21 */ - YYSYMBOL_using_declaration = 269, /* using_declaration */ - YYSYMBOL_simple_type = 270, /* simple_type */ - YYSYMBOL_simple_int_type = 271, /* simple_int_type */ - YYSYMBOL_simple_float_type = 272, /* simple_float_type */ - YYSYMBOL_simple_void_type = 273, /* simple_void_type */ - YYSYMBOL_code = 274, /* code */ - YYSYMBOL_275_22 = 275, /* $@22 */ - YYSYMBOL_code_block = 276, /* code_block */ - YYSYMBOL_element = 277, /* element */ - YYSYMBOL_optional_const_expr = 278, /* optional_const_expr */ - YYSYMBOL_optional_const_expr_comma = 279, /* optional_const_expr_comma */ - YYSYMBOL_const_expr_comma = 280, /* const_expr_comma */ - YYSYMBOL_no_angle_bracket_const_expr = 281, /* no_angle_bracket_const_expr */ - YYSYMBOL_const_expr = 282, /* const_expr */ - YYSYMBOL_const_operand = 283, /* const_operand */ - YYSYMBOL_formal_const_expr = 284, /* formal_const_expr */ - YYSYMBOL_formal_const_operand = 285, /* formal_const_operand */ - YYSYMBOL_capture_list = 286, /* capture_list */ - YYSYMBOL_capture = 287, /* capture */ - YYSYMBOL_class_derivation_name = 288, /* class_derivation_name */ - YYSYMBOL_name = 289, /* name */ - YYSYMBOL_name_no_final = 290, /* name_no_final */ - YYSYMBOL_string_literal = 291, /* string_literal */ - YYSYMBOL_empty = 292 /* empty */ -}; -typedef enum yysymbol_kind_t yysymbol_kind_t; - - - - -#ifdef short -# undef short -#endif - -/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure - and (if available) are included - so that the code can choose integer types of a good width. */ - -#ifndef __PTRDIFF_MAX__ -# include /* INFRINGES ON USER NAME SPACE */ -# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_STDINT_H -# endif -#endif - -/* Narrow types that promote to a signed type and that can represent a - signed or unsigned integer of at least N bits. In tables they can - save space and decrease cache pressure. Promoting to a signed type - helps avoid bugs in integer arithmetic. */ - -#ifdef __INT_LEAST8_MAX__ -typedef __INT_LEAST8_TYPE__ yytype_int8; -#elif defined YY_STDINT_H -typedef int_least8_t yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef __INT_LEAST16_MAX__ -typedef __INT_LEAST16_TYPE__ yytype_int16; -#elif defined YY_STDINT_H -typedef int_least16_t yytype_int16; -#else -typedef short yytype_int16; -#endif - -/* Work around bug in HP-UX 11.23, which defines these macros - incorrectly for preprocessor constants. This workaround can likely - be removed in 2023, as HPE has promised support for HP-UX 11.23 - (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of - . */ -#ifdef __hpux -# undef UINT_LEAST8_MAX -# undef UINT_LEAST16_MAX -# define UINT_LEAST8_MAX 255 -# define UINT_LEAST16_MAX 65535 -#endif - -#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST8_TYPE__ yytype_uint8; -#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST8_MAX <= INT_MAX) -typedef uint_least8_t yytype_uint8; -#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX -typedef unsigned char yytype_uint8; -#else -typedef short yytype_uint8; -#endif - -#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST16_TYPE__ yytype_uint16; -#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST16_MAX <= INT_MAX) -typedef uint_least16_t yytype_uint16; -#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX -typedef unsigned short yytype_uint16; -#else -typedef int yytype_uint16; -#endif - -#ifndef YYPTRDIFF_T -# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ -# define YYPTRDIFF_T __PTRDIFF_TYPE__ -# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ -# elif defined PTRDIFF_MAX -# ifndef ptrdiff_t -# include /* INFRINGES ON USER NAME SPACE */ -# endif -# define YYPTRDIFF_T ptrdiff_t -# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX -# else -# define YYPTRDIFF_T long -# define YYPTRDIFF_MAXIMUM LONG_MAX -# endif -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned -# endif -#endif - -#define YYSIZE_MAXIMUM \ - YY_CAST (YYPTRDIFF_T, \ - (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ - ? YYPTRDIFF_MAXIMUM \ - : YY_CAST (YYSIZE_T, -1))) - -#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) - - -/* Stored state numbers (used for stacks). */ -typedef yytype_int16 yy_state_t; - -/* State numbers in computations. */ -typedef int yy_state_fast_t; - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - - -#ifndef YY_ATTRIBUTE_PURE -# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define YY_ATTRIBUTE_PURE -# endif -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# else -# define YY_ATTRIBUTE_UNUSED -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YY_USE(E) ((void) (E)) -#else -# define YY_USE(E) /* empty */ -#endif - -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ -# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") -# else -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# endif -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ -# define YY_IGNORE_USELESS_CAST_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") -# define YY_IGNORE_USELESS_CAST_END \ - _Pragma ("GCC diagnostic pop") -#endif -#ifndef YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_END -#endif - - -#define YY_ASSERT(E) ((void) (0 && (E))) - -#if !defined yyoverflow - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* !defined yyoverflow */ - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ - && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yy_state_t yyss_alloc; - YYSTYPE yyvs_alloc; - YYLTYPE yyls_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ - + YYSIZEOF (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYPTRDIFF_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / YYSIZEOF (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYPTRDIFF_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 109 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 6863 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 180 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 113 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 789 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 1678 - -/* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 410 - - -/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) \ - (0 <= (YYX) && (YYX) <= YYMAXUTOK \ - ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ - : YYSYMBOL_YYUNDEF) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 178, 2, 2, 2, 171, 164, 2, - 174, 176, 169, 167, 157, 168, 173, 170, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 159, 158, - 165, 160, 166, 161, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 175, 2, 179, 163, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 156, 162, 177, 172, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155 -}; - -#if YYDEBUG -/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_int16 yyrline[] = -{ - 0, 466, 466, 467, 471, 478, 479, 486, 485, 496, - 497, 501, 505, 509, 522, 521, 533, 534, 535, 536, - 537, 538, 539, 552, 561, 565, 573, 577, 581, 602, - 629, 650, 679, 715, 758, 770, 791, 827, 861, 883, - 919, 941, 952, 966, 965, 980, 984, 989, 993, 1004, - 1008, 1012, 1016, 1020, 1029, 1033, 1037, 1041, 1045, 1049, - 1053, 1057, 1061, 1068, 1072, 1077, 1085, 1090, 1098, 1102, - 1110, 1115, 1124, 1123, 1139, 1149, 1148, 1165, 1173, 1181, - 1193, 1210, 1209, 1224, 1239, 1249, 1265, 1264, 1307, 1306, - 1335, 1334, 1372, 1371, 1403, 1402, 1422, 1421, 1443, 1442, - 1475, 1474, 1501, 1514, 1518, 1522, 1526, 1530, 1539, 1543, - 1547, 1551, 1555, 1560, 1565, 1569, 1573, 1580, 1584, 1588, - 1592, 1596, 1600, 1604, 1608, 1612, 1616, 1620, 1624, 1628, - 1632, 1636, 1640, 1644, 1648, 1652, 1656, 1660, 1664, 1668, - 1672, 1676, 1680, 1684, 1688, 1692, 1696, 1700, 1704, 1708, - 1712, 1716, 1720, 1724, 1728, 1732, 1736, 1743, 1744, 1745, - 1749, 1751, 1750, 1758, 1759, 1763, 1764, 1768, 1774, 1783, - 1784, 1788, 1792, 1796, 1800, 1806, 1812, 1818, 1825, 1830, - 1836, 1843, 1852, 1856, 1861, 1869, 1881, 1885, 1899, 1914, - 1919, 1924, 1929, 1934, 1939, 1944, 1949, 1955, 1954, 1985, - 1995, 2005, 2009, 2013, 2022, 2026, 2034, 2038, 2043, 2047, - 2052, 2060, 2065, 2073, 2077, 2082, 2086, 2091, 2099, 2104, - 2112, 2116, 2123, 2127, 2134, 2138, 2142, 2146, 2150, 2157, - 2161, 2165, 2169, 2173, 2177, 2184, 2185, 2186, 2190, 2193, - 2194, 2195, 2199, 2211, 2230, 2234, 2244, 2248, 2252, 2257, - 2262, 2267, 2272, 2277, 2282, 2287, 2295, 2299, 2303, 2308, - 2313, 2318, 2323, 2328, 2333, 2338, 2343, 2349, 2357, 2362, - 2367, 2372, 2377, 2382, 2387, 2392, 2397, 2402, 2407, 2413, - 2421, 2425, 2430, 2435, 2440, 2445, 2450, 2455, 2460, 2465, - 2470, 2478, 2482, 2487, 2492, 2497, 2502, 2507, 2512, 2517, - 2522, 2527, 2532, 2538, 2545, 2552, 2562, 2566, 2574, 2578, - 2582, 2586, 2590, 2606, 2622, 2631, 2635, 2645, 2649, 2656, - 2667, 2671, 2679, 2683, 2687, 2691, 2695, 2711, 2727, 2745, - 2754, 2758, 2768, 2772, 2779, 2783, 2791, 2795, 2811, 2827, - 2836, 2846, 2850, 2857, 2861, 2869, 2873, 2878, 2882, 2891, - 2890, 2915, 2914, 2944, 2945, 2952, 2953, 2957, 2958, 2962, - 2966, 2970, 2974, 2978, 2982, 2986, 2990, 2994, 2998, 3006, - 3005, 3022, 3026, 3030, 3035, 3043, 3047, 3054, 3055, 3060, - 3067, 3068, 3073, 3081, 3085, 3089, 3096, 3100, 3104, 3112, - 3111, 3134, 3133, 3156, 3157, 3161, 3167, 3174, 3180, 3189, - 3190, 3191, 3195, 3199, 3203, 3207, 3211, 3215, 3219, 3224, - 3229, 3234, 3239, 3243, 3248, 3257, 3262, 3270, 3274, 3278, - 3286, 3296, 3296, 3306, 3307, 3311, 3312, 3313, 3314, 3315, - 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3322, 3322, 3323, - 3323, 3323, 3323, 3323, 3324, 3324, 3324, 3324, 3324, 3325, - 3325, 3325, 3326, 3326, 3326, 3326, 3326, 3327, 3327, 3327, - 3327, 3327, 3328, 3328, 3329, 3329, 3329, 3329, 3329, 3330, - 3330, 3330, 3330, 3330, 3330, 3331, 3331, 3331, 3331, 3331, - 3332, 3332, 3332, 3332, 3332, 3333, 3333, 3333, 3333, 3333, - 3334, 3334, 3334, 3334, 3334, 3335, 3335, 3335, 3335, 3335, - 3335, 3336, 3336, 3336, 3336, 3336, 3337, 3337, 3337, 3337, - 3338, 3338, 3338, 3338, 3339, 3339, 3339, 3339, 3339, 3339, - 3340, 3340, 3340, 3340, 3341, 3341, 3341, 3341, 3341, 3342, - 3342, 3342, 3342, 3343, 3343, 3343, 3343, 3343, 3344, 3344, - 3347, 3347, 3347, 3347, 3347, 3347, 3347, 3347, 3347, 3347, - 3347, 3348, 3348, 3348, 3348, 3348, 3348, 3348, 3348, 3348, - 3348, 3349, 3349, 3353, 3357, 3364, 3368, 3375, 3379, 3386, - 3390, 3394, 3398, 3402, 3406, 3410, 3414, 3418, 3422, 3426, - 3430, 3434, 3438, 3442, 3446, 3450, 3454, 3458, 3462, 3466, - 3470, 3474, 3478, 3482, 3486, 3490, 3494, 3498, 3502, 3506, - 3510, 3514, 3518, 3522, 3526, 3530, 3534, 3538, 3542, 3550, - 3554, 3558, 3562, 3566, 3570, 3574, 3584, 3594, 3600, 3606, - 3612, 3618, 3624, 3630, 3636, 3643, 3650, 3657, 3664, 3670, - 3676, 3680, 3684, 3688, 3692, 3696, 3700, 3711, 3722, 3726, - 3730, 3734, 3738, 3742, 3746, 3750, 3754, 3758, 3762, 3766, - 3770, 3774, 3778, 3782, 3786, 3790, 3794, 3798, 3802, 3806, - 3810, 3814, 3818, 3822, 3826, 3830, 3834, 3838, 3842, 3846, - 3850, 3857, 3861, 3865, 3869, 3873, 3877, 3881, 3885, 3889, - 3895, 3901, 3905, 3912, 3920, 3924, 3928, 3932, 3936, 3940, - 3944, 3948, 3952, 3956, 3960, 3964, 3968, 3972, 3976, 3980, - 3984, 3988, 4002, 4006, 4010, 4014, 4018, 4022, 4026, 4030, - 4034, 4038, 4042, 4046, 4050, 4061, 4072, 4076, 4080, 4084, - 4088, 4092, 4096, 4100, 4104, 4108, 4112, 4116, 4120, 4124, - 4128, 4132, 4136, 4140, 4144, 4148, 4152, 4156, 4160, 4164, - 4168, 4172, 4176, 4180, 4184, 4188, 4192, 4199, 4203, 4207, - 4211, 4215, 4219, 4223, 4227, 4231, 4237, 4243, 4251, 4255, - 4259, 4263, 4270, 4280, 4286, 4292, 4302, 4314, 4322, 4326, - 4356, 4360, 4364, 4368, 4372, 4376, 4382, 4386, 4390, 4394, - 4398, 4409, 4413, 4417, 4421, 4429, 4433, 4437, 4443, 4454 -}; -#endif - -/** Accessing symbol of state STATE. */ -#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) - -#if YYDEBUG || 0 -/* The user-facing name of the symbol whose (internal) number is - YYSYMBOL. No bounds checking. */ -static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; - -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "\"end of file\"", "error", "\"invalid token\"", "REAL", "INTEGER", - "CHAR_TOK", "SIMPLE_STRING", "SIMPLE_IDENTIFIER", "STRING_LITERAL", - "CUSTOM_LITERAL", "IDENTIFIER", "TYPENAME_IDENTIFIER", - "TYPEPACK_IDENTIFIER", "SCOPING", "TYPEDEFNAME", "ELLIPSIS", "OROR", - "ANDAND", "EQCOMPARE", "NECOMPARE", "LECOMPARE", "GECOMPARE", - "SPACESHIP", "LSHIFT", "RSHIFT", "POINTSAT_STAR", "DOT_STAR", "UNARY", - "UNARY_NOT", "UNARY_NEGATE", "UNARY_MINUS", "UNARY_PLUS", "UNARY_STAR", - "UNARY_REF", "POINTSAT", "SCOPE", "PLUSPLUS", "MINUSMINUS", "TIMESEQUAL", - "DIVIDEEQUAL", "MODEQUAL", "PLUSEQUAL", "MINUSEQUAL", "OREQUAL", - "ANDEQUAL", "XOREQUAL", "LSHIFTEQUAL", "RSHIFTEQUAL", "ATTR_LEFT", - "ATTR_RIGHT", "KW_ALIGNAS", "KW_ALIGNOF", "KW_AUTO", "KW_BEGIN_PUBLISH", - "KW_BLOCKING", "KW_BOOL", "KW_BUILTIN_VA_LIST", "KW_CATCH", "KW_CHAR", - "KW_CHAR8_T", "KW_CHAR16_T", "KW_CHAR32_T", "KW_CLASS", "KW_CONST", - "KW_CONSTEVAL", "KW_CONSTEXPR", "KW_CONSTINIT", "KW_CONST_CAST", - "KW_DECLTYPE", "KW_DEFAULT", "KW_DELETE", "KW_DOUBLE", "KW_DYNAMIC_CAST", - "KW_ELSE", "KW_END_PUBLISH", "KW_ENUM", "KW_EXTENSION", "KW_EXTERN", - "KW_EXPLICIT", "KW_EXPLICIT_LPAREN", "KW_PUBLISHED", "KW_FALSE", - "KW_FINAL", "KW_FLOAT", "KW_FRIEND", "KW_FOR", "KW_GOTO", - "KW_HAS_VIRTUAL_DESTRUCTOR", "KW_IF", "KW_INLINE", "KW_INT", - "KW_IS_ABSTRACT", "KW_IS_BASE_OF", "KW_IS_CLASS", "KW_IS_CONSTRUCTIBLE", - "KW_IS_CONVERTIBLE_TO", "KW_IS_DESTRUCTIBLE", "KW_IS_EMPTY", - "KW_IS_ENUM", "KW_IS_FINAL", "KW_IS_FUNDAMENTAL", "KW_IS_POD", - "KW_IS_POLYMORPHIC", "KW_IS_STANDARD_LAYOUT", "KW_IS_TRIVIAL", - "KW_IS_TRIVIALLY_COPYABLE", "KW_IS_UNION", "KW_LONG", - "KW_MAKE_MAP_KEYS_SEQ", "KW_MAKE_MAP_PROPERTY", "KW_MAKE_PROPERTY", - "KW_MAKE_PROPERTY2", "KW_MAKE_SEQ", "KW_MAKE_SEQ_PROPERTY", "KW_MUTABLE", - "KW_NAMESPACE", "KW_NEW", "KW_NOEXCEPT", "KW_NOEXCEPT_LPAREN", - "KW_NULLPTR", "KW_OPERATOR", "KW_OVERRIDE", "KW_PRIVATE", "KW_PROTECTED", - "KW_PUBLIC", "KW_REGISTER", "KW_REINTERPRET_CAST", "KW_RESTRICT", - "KW_RETURN", "KW_SHORT", "KW_SIGNED", "KW_SIZEOF", "KW_STATIC", - "KW_STATIC_ASSERT", "KW_STATIC_CAST", "KW_STRUCT", "KW_TEMPLATE", - "KW_THREAD_LOCAL", "KW_THROW", "KW_TRUE", "KW_TRY", "KW_TYPEDEF", - "KW_TYPEID", "KW_TYPENAME", "KW_UNDERLYING_TYPE", "KW_UNION", - "KW_UNSIGNED", "KW_USING", "KW_VIRTUAL", "KW_VOID", "KW_VOLATILE", - "KW_WCHAR_T", "KW_WHILE", "START_CPP", "START_CONST_EXPR", "START_TYPE", - "'{'", "','", "';'", "':'", "'='", "'?'", "'|'", "'^'", "'&'", "'<'", - "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", "'~'", "'.'", "'('", "'['", - "')'", "'}'", "'!'", "']'", "$accept", "grammar", "cpp", "$@1", - "constructor_inits", "constructor_init", "extern_c", "$@2", - "declaration", "friend_declaration", "$@3", "storage_class", - "optional_attributes", "attribute_specifiers", "attribute_specifier", - "type_like_declaration", "$@4", "$@5", "multiple_instance_identifiers", - "typedef_declaration", "$@6", "typedef_instance_identifiers", - "constructor_prototype", "$@7", "$@8", "$@9", "function_prototype", - "$@10", "$@11", "$@12", "$@13", "$@14", "function_post", - "function_operator", "more_template_declaration", "template_declaration", - "$@15", "template_formal_parameters", - "template_nonempty_formal_parameters", "typename_keyword", - "template_formal_parameter", "template_formal_parameter_type", - "instance_identifier", "$@16", - "instance_identifier_and_maybe_trailing_return_type", - "maybe_trailing_return_type", "maybe_comma_identifier", - "function_parameter_list", "function_parameters", - "formal_parameter_list", "formal_parameters", - "template_parameter_maybe_initialize", "maybe_initialize", - "maybe_initialize_or_constructor_body", - "maybe_initialize_or_function_body", "structure_init", - "structure_init_body", "function_parameter", "formal_parameter", - "not_paren_formal_parameter_identifier", "formal_parameter_identifier", - "parameter_pack_identifier", "not_paren_empty_instance_identifier", - "empty_instance_identifier", "type", "type_pack", "type_decl", - "predefined_type", "var_type_decl", "full_type", "anonymous_struct", - "$@17", "named_struct", "$@18", "maybe_final", "maybe_class_derivation", - "class_derivation", "base_specification", "enum", "$@19", "enum_decl", - "enum_element_type", "enum_body_trailing_comma", "enum_body", - "enum_keyword", "struct_keyword", "namespace_declaration", "$@20", - "$@21", "using_declaration", "simple_type", "simple_int_type", - "simple_float_type", "simple_void_type", "code", "$@22", "code_block", - "element", "optional_const_expr", "optional_const_expr_comma", - "const_expr_comma", "no_angle_bracket_const_expr", "const_expr", - "const_operand", "formal_const_expr", "formal_const_operand", - "capture_list", "capture", "class_derivation_name", "name", - "name_no_final", "string_literal", "empty", YY_NULLPTR -}; - -static const char * -yysymbol_name (yysymbol_kind_t yysymbol) -{ - return yytname[yysymbol]; -} -#endif - -#define YYPACT_NINF (-1062) - -#define yypact_value_is_default(Yyn) \ - ((Yyn) == YYPACT_NINF) - -#define YYTABLE_NINF (-785) - -#define yytable_value_is_error(Yyn) \ - 0 - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 188, -1062, 4339, 6032, 93, 349, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, 81, -70, -59, -43, -23, -2, - 24, 44, 60, 91, -1062, -1062, 92, 100, 109, 143, - 146, 154, 177, 180, 192, 200, 243, 251, 255, 264, - 272, 275, 279, 283, 290, 317, 6228, 4339, -1062, -1062, - 216, 324, 346, 3187, 221, -1062, 351, 368, 387, 4339, - 4339, 4339, 4339, 4339, 2888, 581, 4339, 4754, -1062, 119, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - 6097, 389, -1062, 6, -1062, -1062, 1578, 2508, 2508, -1062, - 5064, 414, -1062, 2508, -1062, -1062, 833, 833, -1062, -1062, - -1062, -1062, -1062, 223, 223, -1062, -1062, -1062, -1062, -1062, - 2565, 416, 274, -1062, 4339, 4339, 6032, 4339, 4339, 4339, - 4339, 4339, 6032, 4339, 6032, 4339, 6032, 4339, 6032, 6032, - 6032, 6032, 6032, 6032, 6032, 6032, 6032, 6032, 6032, 6032, - 6032, 6032, 6032, 6032, 4339, -1062, -1062, -1062, 421, 5064, - 423, 433, 223, 223, -1062, 5284, 6032, 4339, 4339, 453, - 2888, 68, 6032, 2888, 4339, 4339, 68, 68, 68, 68, - 68, 81, -59, -43, -23, -2, 24, 60, 92, 109, - 5288, 6413, 6437, 6513, 387, 376, -36, 4754, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - 5064, 5064, -104, 397, -1062, -1062, 68, 4339, 4339, 4339, - 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, - 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 5064, 3331, - 4339, -1062, -1062, 833, 833, 3475, -1062, -1062, -1062, 2508, - -1062, -1062, -1062, -1062, 6032, -1062, 432, 564, 223, 833, - 833, 833, 223, 223, 59, 462, -1062, 463, -1062, 473, - 87, 2050, 5064, 583, 487, 474, 3037, -1062, 6616, 465, - 500, -1062, 494, 496, 506, 511, 516, 525, 528, 483, - 530, 495, 531, 532, 533, 534, 536, 543, -15, 563, - 551, 556, 562, 566, 567, 568, 572, 573, 576, 582, - 584, 587, 4339, -1062, 6032, 4339, 5064, 5064, -1062, 546, - 589, 590, 5064, 592, 574, 593, 5303, 596, 597, 4339, - 4339, -1062, 732, -1062, 1631, 600, 4339, -1062, -1062, 1881, - 4935, 5120, 5120, 555, 555, 485, 298, 298, -1062, 3642, - 5661, 1606, 1809, 555, 555, 132, 132, 68, 68, 68, - -1062, -1062, 28, 2457, -1062, -1062, 604, 5345, 613, 223, - 223, 1104, 462, -1062, 462, -1062, 462, -1062, 1104, 1104, - -1062, 223, 223, 223, 6713, 621, 30, -1062, 622, 4339, - -1062, -1062, -1062, -1062, -1062, 2131, 634, 3, 41, 57, - 106, -1062, -1062, -1062, 640, 223, 5064, 2062, 81, -1062, - -1062, 628, 5064, 632, 638, -1062, -1062, -1062, 223, 223, - -1062, 5366, -1062, 6713, 6713, 6713, 6713, 6713, -1062, 6713, - 5814, 6713, 4339, 656, -1062, 6656, 644, 645, 646, 647, - 648, 649, 6713, 62, 667, 669, 673, 6713, 6713, 660, - 6551, 6713, 6713, 4685, 6713, 6713, -1062, -1062, -1062, 2526, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, 663, -1062, 664, -1062, -1062, -1062, -1062, - 6032, -1062, 6032, -1062, 6032, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, 5385, 665, 671, - -1062, -1062, 666, -1062, -1062, 675, 4483, 678, -1062, -1062, - -1062, -1062, 68, 4754, -1062, 5064, 397, 55, 5806, -1062, - 4754, 4339, -1062, -1062, -1062, -1062, -1062, 1104, 668, 670, - 5064, 223, 1104, 1104, 1104, 223, 223, 674, -1062, 674, - 674, 1104, 1104, 1104, 5889, 6713, 6097, -1062, -1062, 117, - 679, 4754, -1062, 5064, 676, -1062, -1062, -1062, -1062, 2131, - -1062, 763, 5064, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, 686, 697, 701, -1062, -1062, 6228, -1062, -1062, 702, - 4880, 710, -1062, 695, 4339, 4339, 4339, 4339, 2888, 4339, - 700, 42, -1062, -1062, 5644, -1062, 119, 703, 3619, -1062, - 6032, 223, 2581, 2050, 223, -1062, -1062, -1062, -1062, -1062, - -1062, 6713, -1062, -1062, -1062, 5404, -1062, 6616, 3389, -1062, - 5064, 5064, 5064, 5064, 5064, 5064, -1062, -1062, 5064, -1062, - -1062, -1062, -1062, -1062, 4339, -1062, 5109, -1062, 712, -1062, - 5209, -1062, 5064, 5064, 2, -1062, -1062, 457, 706, 6130, - -1062, 5064, -1062, 224, 723, -1062, 4339, 4339, 709, 711, - 713, -1062, -1062, -1062, 4339, -1062, 4339, -1062, 715, -1062, - -1062, -1062, -1062, -1062, -1062, 4339, -1062, 708, -1062, -1062, - 852, 4754, 674, 223, 223, 1104, 674, 674, 674, 1104, - 1104, 4339, -103, 85, 133, 977, 946, 5806, -1062, -1062, - 223, 223, -1062, 736, 58, -1062, 729, -1062, 844, 6032, - 6032, 6032, 721, 6032, 725, 2888, 95, 6032, 2888, 68, - 68, 68, 68, 726, 101, 68, -1062, -1062, 4863, 4339, - 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, - 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, - 5064, 3763, 4339, 727, 5464, 731, -1062, -1062, 746, -1062, - -1062, -1062, 6713, -1062, -1062, 753, 757, 759, 760, 764, - 769, 770, 80, 772, 4506, 5921, 395, 755, 224, -1062, - -1062, 773, 774, -1062, 775, -1062, 22, 6293, 1248, -1062, - 756, 517, -1062, -1062, 2204, -1062, -1062, 704, 124, 183, - -1062, -1062, -1062, 189, 196, -1062, 5565, 365, 6195, 777, - -1062, 1104, -1062, 674, 674, 674, 762, 778, 784, 788, - 765, 223, 977, 977, 977, 223, 223, 977, -81, 223, - -1062, 767, 5064, 223, 946, 946, 946, 223, 223, 946, - 8, 852, 771, 36, -1062, 6311, 791, 794, -1062, 223, - 790, 782, 798, 4339, 801, 5064, 792, 809, 800, 5584, - 4339, -1062, -1062, -1062, 1881, 4935, 5120, 5120, 555, 555, - 485, 298, 298, -1062, 3930, 5661, 1606, 1809, 555, 555, - 132, 132, 68, 68, 68, -1062, -1062, 207, 2907, -1062, - -1062, -1062, 2131, -1062, 98, -1062, 969, 971, 972, 974, - 975, 976, -1062, -1062, 427, 835, -1062, -1062, -1062, -1062, - 5975, -1062, 5975, 825, 838, 6470, -1062, 744, -1062, -1062, - 20, -1062, 704, -1062, -1062, 6032, 55, 820, 829, 704, - 55, 1248, 830, 223, 1248, 1248, 1248, 223, 223, 56, - 223, -1062, 99, -1062, -1062, -1062, 5064, 405, -1062, 826, - -1062, 848, 850, 3907, 4214, 842, 223, 704, 5043, 704, - 223, 223, 704, -1062, 77, 454, 223, -1062, -1062, -1062, - -1062, 5806, -1062, -1062, 14, 6228, 833, -1062, 674, 223, - 55, 55, 55, 223, 977, 837, 837, 837, 977, 977, - 328, 4339, -1062, -1062, 223, 223, 946, 840, 840, 840, - 946, 946, 336, 4339, -1062, -1062, -1062, 4339, 6378, 6393, - 6408, 5064, 498, -1062, -1062, 998, -1062, 6311, -1062, -1062, - 843, 849, 846, 854, 856, 4483, 865, -1062, -1062, 68, - 4339, -1062, -1062, 736, -1062, -1062, 861, 212, 873, 884, - 889, 895, -1062, 43, -1062, 744, 744, 6696, 5921, 5064, - 885, 897, 223, 744, 744, 744, 223, 223, 744, 65, - 840, -1062, 454, 910, 893, 898, 704, 492, 899, 410, - 223, 1248, 901, 901, 901, 1248, 1248, -1062, 4339, -1062, - -1062, 55, 900, 468, -1062, 89, 916, 920, -1062, 2711, - -1062, -1062, -1062, 3907, 902, 923, 4754, -1062, -1062, 223, - 704, 460, 1071, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - 909, 907, -1062, 223, 460, 704, 704, 515, 4339, -1062, - 4339, -1062, 2204, 931, -1062, -1062, 852, 913, -1062, 833, - -1062, 914, -1062, 917, 919, 924, 977, 837, 837, 837, - 918, 911, 946, -1062, 840, 840, 840, 925, 922, 5625, - 1336, -1062, 1336, -1062, 1336, -1062, -1062, 1336, 1336, 1336, - -1062, 102, -1062, 4339, 4339, -1062, 4339, -1062, 4339, 4754, - 134, 1092, 1093, 948, 1097, 932, -1062, 1099, 1106, 1108, - 157, 956, 65, 840, 65, 840, -1062, -1062, -1062, -1062, - -1062, -1062, 6032, 223, 744, 744, 744, 1788, -1062, -1062, - 965, -1062, -1062, -1062, -1062, 523, 951, -1062, -1062, 1248, - 901, 901, 901, 55, 952, 958, -1062, -1062, 5064, 4339, - 4339, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - -1062, -1062, 955, -1062, 4051, 704, 460, 223, -1062, -1062, - -1062, 460, 460, -1062, 4754, 2062, 964, 4214, 704, 979, - -1062, -1062, -1062, -1062, -1062, -1062, 837, 55, 223, 840, - 55, 223, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, - 230, 252, 254, 266, -1062, 968, 304, -1062, 990, 991, - 325, 982, 339, -1062, -1062, -1062, -1062, -1062, 744, 978, - 985, 988, 994, 4627, 997, 1788, 1788, 1788, 1788, 1788, - 2888, 1788, 1343, -1062, 704, 5806, 55, 989, -1062, 5806, - 55, 901, 992, 223, -1062, 987, -1062, 993, 996, 2382, - -1062, 3907, 4754, 460, -1062, 999, 223, -1062, -1062, 5806, - 5806, 5806, 1000, -1062, 1001, -1062, -1062, -1062, -1062, -1062, - 1011, 1163, 1016, 1168, -1062, 1170, 1023, 1024, 1174, 1027, - 6032, 6032, 6032, 6032, 1012, 2888, 152, 6032, 152, 152, - 152, 152, 152, 1013, 367, 152, 1788, 1788, 1788, 1788, - 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, - 1788, 1788, 1788, 1788, 1788, 5064, 4195, 4339, -1062, -1062, - 1014, -1062, 55, -1062, 1015, -1062, -1062, 5806, -1062, -1062, - 1172, -1062, 1019, -1062, -1062, 1021, 852, 852, 852, -1062, - -1062, -1062, 1036, -1062, 1026, 1042, -1062, -1062, 369, -1062, - 1028, 1034, 1039, 1041, 5064, 1032, 1043, 1788, -1062, 1911, - 4954, 1257, 1257, 888, 888, 1441, 617, 617, -1062, 1363, - 5678, 5743, 4478, 281, 281, 152, 152, 152, -1062, -1062, - 370, 3205, -1062, 55, 1035, -1062, 3534, -1062, -1062, -1062, - 5806, -1062, -1062, -1062, -1062, 5806, 5806, 1200, 1040, 1054, - 1208, 1209, 1062, -1062, 1047, 1049, 1050, 1051, 4731, 1055, - 152, 1788, -1062, -1062, 5806, 1057, -1062, 3534, -1062, -1062, - -1062, -1062, 1067, -1062, 1058, 371, -1062, 4339, 4339, 4339, - -1062, 4339, 1343, -1062, -1062, 5806, -1062, 1072, 1225, 1078, - 372, 378, 380, 383, 5806, 852, -1062, 1064, -1062, -1062, - -1062, -1062, -1062, 852, -1062, 1083, -1062, -1062 -}; - -/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_int16 yydefact[] = -{ - 0, 789, 0, 0, 0, 789, 5, 675, 671, 674, - 785, 786, 677, 678, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 673, 679, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 681, 680, - 0, 0, 0, 0, 0, 672, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 789, 0, 3, 609, 676, - 307, 319, 317, 402, 318, 403, 405, 406, 407, 386, - 0, 0, 418, 383, 417, 412, 409, 408, 411, 387, - 0, 0, 388, 410, 420, 404, 789, 789, 4, 309, - 310, 311, 369, 789, 789, 306, 399, 400, 401, 1, - 0, 0, 7, 63, 789, 789, 0, 789, 789, 789, - 789, 789, 0, 789, 0, 789, 0, 789, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 789, 335, 341, 342, 0, 0, - 0, 634, 789, 789, 334, 0, 0, 789, 789, 0, - 0, 631, 0, 0, 789, 789, 643, 641, 640, 642, - 639, 307, 402, 403, 405, 406, 407, 418, 417, 412, - 409, 408, 411, 410, 404, 0, 0, 567, 770, 771, - 772, 780, 773, 776, 774, 778, 777, 775, 779, 759, - 760, 0, 0, 789, 765, 758, 638, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 787, 788, 789, 789, 0, 384, 385, 419, 409, - 414, 413, 416, 308, 0, 415, 0, 292, 789, 789, - 789, 789, 789, 789, 789, 0, 345, 291, 347, 0, - 372, 0, 0, 0, 68, 70, 0, 6, 789, 0, - 566, 565, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 336, 0, 789, 0, 0, 667, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 670, 763, 766, 0, 789, 0, 761, 222, 652, - 653, 654, 655, 656, 657, 658, 661, 662, 669, 0, - 649, 650, 651, 659, 660, 647, 648, 644, 645, 646, - 668, 666, 0, 0, 346, 348, 0, 0, 0, 789, - 789, 789, 0, 294, 0, 296, 0, 295, 789, 789, - 207, 789, 789, 789, 789, 0, 208, 211, 63, 789, - 789, 781, 782, 783, 784, 0, 374, 770, 771, 772, - 774, 349, 312, 351, 0, 789, 0, 789, 321, 332, - 333, 0, 0, 0, 0, 323, 324, 325, 789, 789, - 320, 0, 22, 789, 789, 789, 789, 789, 23, 789, - 789, 789, 0, 0, 43, 789, 0, 0, 0, 0, - 0, 0, 789, 789, 0, 0, 0, 789, 789, 0, - 789, 789, 789, 0, 789, 789, 18, 8, 20, 0, - 16, 17, 19, 78, 45, 616, 615, 633, 623, 618, - 620, 621, 622, 0, 629, 0, 628, 684, 617, 685, - 0, 687, 0, 688, 0, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 625, 0, 0, 0, - 338, 337, 0, 624, 627, 0, 630, 0, 636, 637, - 626, 619, 610, 568, 764, 0, 789, 789, 789, 103, - 223, 0, 665, 664, 315, 314, 316, 789, 293, 0, - 281, 789, 789, 789, 789, 789, 789, 299, 280, 298, - 297, 789, 789, 789, 789, 789, 0, 789, 210, 789, - 0, 564, 563, 380, 0, 377, 376, 371, 375, 0, - 789, 789, 0, 64, 69, 751, 747, 750, 753, 754, - 214, 0, 0, 0, 749, 755, 0, 757, 756, 0, - 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, - 0, 215, 244, 218, 245, 702, 752, 63, 0, 322, - 0, 789, 372, 0, 789, 60, 46, 57, 58, 59, - 61, 789, 47, 160, 52, 0, 24, 789, 0, 50, - 0, 0, 0, 0, 0, 0, 56, 789, 0, 27, - 26, 25, 54, 49, 0, 164, 0, 163, 0, 62, - 0, 21, 0, 0, 789, 51, 55, 344, 321, 0, - 14, 0, 75, 0, 343, 72, 0, 0, 0, 0, - 0, 339, 340, 635, 0, 632, 0, 762, 0, 111, - 104, 113, 108, 112, 106, 0, 109, 0, 105, 110, - 789, 663, 300, 789, 789, 789, 283, 285, 284, 789, - 789, 789, 0, 0, 0, 789, 0, 789, 209, 212, - 789, 789, 370, 313, 789, 354, 789, 353, 0, 0, - 0, 0, 712, 0, 0, 0, 709, 0, 0, 720, - 719, 718, 717, 0, 0, 716, 71, 217, 789, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 67, 328, 374, 326, - 66, 48, 789, 44, 789, 0, 0, 0, 0, 0, - 0, 0, 789, 0, 0, 789, 344, 321, 0, 343, - 81, 0, 0, 395, 0, 86, 90, 0, 789, 789, - 0, 0, 421, 229, 0, 77, 74, 0, 0, 0, - 686, 689, 690, 0, 0, 789, 0, 0, 0, 0, - 201, 789, 282, 288, 287, 286, 0, 0, 0, 0, - 0, 789, 789, 789, 789, 789, 789, 789, 789, 789, - 256, 0, 268, 789, 0, 0, 0, 789, 789, 0, - 789, 789, 301, 381, 350, 0, 0, 356, 355, 789, - 0, 0, 0, 789, 0, 0, 0, 0, 0, 0, - 0, 746, 216, 219, 729, 730, 731, 732, 733, 734, - 735, 738, 739, 745, 0, 726, 727, 728, 736, 737, - 724, 725, 721, 722, 723, 744, 743, 0, 0, 330, - 329, 331, 0, 53, 789, 391, 0, 0, 0, 0, - 0, 0, 393, 389, 0, 0, 183, 184, 185, 169, - 0, 170, 0, 0, 166, 171, 167, 789, 182, 165, - 0, 83, 0, 398, 397, 0, 789, 0, 0, 0, - 789, 789, 0, 789, 789, 789, 789, 789, 789, 0, - 789, 246, 789, 92, 421, 224, 0, 0, 76, 0, - 789, 0, 0, 789, 0, 0, 789, 0, 0, 0, - 789, 789, 0, 73, 789, 789, 789, 613, 612, 614, - 611, 789, 107, 114, 0, 0, 789, 421, 289, 789, - 789, 789, 789, 789, 789, 258, 260, 259, 789, 789, - 0, 789, 242, 257, 789, 789, 0, 270, 272, 271, - 0, 0, 0, 789, 243, 302, 378, 0, 778, 0, - 777, 0, 0, 357, 359, 767, 789, 0, 65, 711, - 0, 0, 0, 0, 0, 708, 0, 714, 715, 703, - 0, 742, 741, 327, 394, 789, 0, 0, 789, 0, - 0, 0, 789, 0, 42, 789, 789, 789, 0, 174, - 172, 0, 789, 789, 789, 789, 789, 789, 789, 789, - 178, 82, 789, 0, 0, 0, 0, 0, 0, 0, - 789, 789, 248, 250, 249, 789, 789, 98, 789, 247, - 15, 789, 0, 0, 9, 0, 0, 0, 230, 422, - 423, 232, 233, 789, 0, 236, 238, 235, 231, 789, - 0, 189, 0, 127, 128, 129, 130, 131, 132, 135, - 136, 137, 152, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 156, 155, 139, 138, 124, - 126, 125, 133, 134, 122, 123, 119, 120, 121, 118, - 0, 0, 117, 789, 190, 0, 0, 0, 0, 197, - 789, 199, 0, 0, 79, 186, 789, 0, 115, 789, - 202, 0, 290, 0, 0, 0, 789, 263, 262, 261, - 267, 0, 0, 269, 275, 274, 273, 279, 0, 382, - 0, 362, 0, 361, 0, 360, 768, 0, 0, 0, - 769, 789, 358, 0, 0, 713, 0, 710, 0, 740, - 789, 0, 0, 0, 0, 0, 204, 0, 0, 0, - 789, 0, 789, 179, 789, 181, 159, 157, 162, 158, - 168, 175, 0, 789, 789, 789, 789, 0, 176, 220, - 0, 84, 396, 789, 88, 0, 0, 789, 100, 789, - 253, 252, 251, 789, 0, 0, 225, 421, 0, 789, - 789, 227, 228, 425, 426, 430, 427, 435, 428, 429, - 431, 432, 433, 434, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 511, 490, - 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, - 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, - 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, - 532, 533, 534, 535, 536, 537, 538, 539, 789, 556, - 557, 558, 549, 561, 545, 546, 544, 551, 552, 540, - 541, 542, 543, 550, 548, 555, 553, 559, 554, 547, - 560, 424, 0, 234, 237, 0, 193, 789, 154, 153, - 187, 192, 191, 196, 200, 789, 0, 223, 0, 0, - 116, 203, 682, 789, 789, 789, 264, 789, 789, 276, - 789, 789, 379, 368, 367, 366, 365, 364, 363, 352, - 0, 0, 0, 0, 392, 0, 0, 34, 205, 0, - 0, 0, 0, 390, 41, 177, 180, 173, 789, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 221, 569, 0, 789, 789, 0, 94, 789, - 789, 254, 0, 789, 789, 0, 10, 0, 0, 0, - 239, 789, 240, 194, 188, 0, 789, 80, 421, 789, - 789, 789, 0, 265, 0, 277, 706, 705, 707, 704, - 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 576, 0, 584, 582, - 581, 583, 580, 0, 0, 579, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 85, 87, - 0, 96, 789, 91, 0, 789, 255, 789, 226, 13, - 11, 562, 0, 789, 195, 0, 789, 789, 789, 789, - 789, 37, 789, 35, 0, 0, 38, 40, 0, 30, - 0, 0, 0, 0, 0, 0, 0, 0, 608, 593, - 594, 595, 596, 597, 598, 599, 600, 601, 607, 0, - 590, 591, 592, 588, 589, 585, 586, 587, 606, 605, - 0, 0, 789, 789, 0, 789, 99, 93, 12, 241, - 789, 683, 305, 304, 303, 789, 789, 0, 0, 0, - 0, 0, 0, 578, 0, 0, 0, 0, 575, 0, - 570, 0, 604, 603, 789, 0, 789, 101, 198, 266, - 278, 205, 0, 29, 0, 0, 31, 0, 0, 0, - 577, 0, 602, 89, 789, 789, 36, 0, 0, 0, - 0, 0, 0, 0, 789, 789, 39, 0, 32, 573, - 572, 574, 571, 789, 95, 0, 97, 33 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -1062, -1062, -525, -1062, -1062, 4, -1062, -1062, 636, -428, - -1062, -354, 210, -358, -1062, -426, -1062, -1062, -153, -1062, - -1062, -208, -1062, -1062, -1062, -1062, 620, -1062, -1062, -1062, - -1062, -1062, -448, -1062, -1062, -414, -1062, -1062, -1062, -1062, - 209, -412, -746, -1062, -886, -775, -311, -406, -1062, -142, - -1062, -644, -485, -1062, -731, -1061, -1062, -381, 537, -844, - -643, 258, -39, -96, -77, -57, -236, -539, 633, 156, - -235, -1062, -223, -1062, -1062, -1062, -1062, 257, -222, -1062, - -1062, -521, -1062, -1062, -27, -22, -1062, -1062, -1062, -1062, - -28, -47, -1062, -1062, -898, -1062, -92, -1062, -623, -110, - -60, 571, 1273, 285, 692, -1062, -1062, 943, -822, 1127, - -116, -395, -1 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - 0, 4, 5, 268, 1073, 1074, 446, 779, 447, 448, - 607, 449, 374, 263, 264, 450, 787, 781, 953, 631, - 912, 1051, 642, 916, 1456, 920, 643, 1071, 1542, 1603, - 1233, 1460, 508, 1133, 1208, 451, 628, 903, 904, 905, - 906, 907, 954, 1395, 955, 799, 1195, 375, 376, 580, - 581, 1218, 327, 938, 785, 1084, 1085, 377, 583, 929, - 975, 987, 255, 256, 96, 97, 644, 151, 645, 98, - 99, 550, 100, 551, 696, 836, 837, 1003, 101, 259, - 102, 547, 543, 544, 103, 104, 452, 1032, 1025, 453, - 105, 106, 107, 108, 939, 940, 1079, 1381, 540, 269, - 270, 1630, 187, 68, 584, 585, 202, 203, 1004, 1005, - 819, 69, 113 -}; - -/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 6, 258, 586, 233, 186, 272, 603, 274, 275, 276, - 277, 278, 625, 280, 627, 282, 582, 284, 154, 152, - 536, 657, 1382, 234, 153, 694, 1052, 702, 693, 1147, - 404, 405, 917, 918, 301, 918, 1072, 911, 554, 240, - 241, 242, 818, 406, 407, 538, 245, 310, 311, 231, - 110, 232, 111, 324, 317, 318, 995, 717, 806, 595, - 596, 597, 598, 599, 205, 600, 602, 604, 236, 1151, - 370, 609, 681, 807, 370, 325, 371, 1059, 616, 326, - 1062, 1063, 1064, 622, 623, -781, 626, 629, 630, 687, - 635, 636, 762, 109, 981, 257, 257, 381, 382, 383, - 186, 658, 216, 110, 116, 111, 110, 110, 111, 111, - 110, 798, 111, 271, 271, 117, 271, 271, 271, 271, - 271, 320, 271, -782, 271, 231, 271, 232, 110, 728, - 111, 118, 688, 240, 241, 242, 245, 354, 355, -783, - 321, 237, 472, 271, 386, 393, 110, 110, 111, 111, - 110, 119, 111, 363, 365, 367, 271, 271, 689, -781, - 773, 473, -781, 271, 271, 110, 216, 111, 326, 352, - 976, 977, 120, 1057, 980, 586, 1171, 1173, 1175, 1141, - 602, 609, 110, 993, 111, 320, 1525, 539, -784, 919, - 1148, 919, 240, 996, 698, 489, 997, -782, 121, 718, - -782, 1091, 328, 1134, 512, 110, 1137, 111, 384, 122, - 362, 364, 366, -783, 405, 112, -783, 1230, 617, 1201, - 185, 1231, 1232, 372, 1144, 1217, 406, 407, 373, 884, - 1067, 1068, 257, 257, 123, 834, 1138, 114, 410, 408, - 981, 228, 229, 230, 409, 1239, 385, 751, 257, 257, - 257, 1139, 1140, 378, 932, 115, 124, 892, 320, 966, - 681, 808, -784, 1240, 1049, -784, 125, 454, 740, 741, - 742, 110, 273, 111, 126, 1024, 1070, 851, 279, 1419, - 281, 320, 283, 127, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, - 957, 225, 226, 227, 271, 228, 229, 230, 681, 809, - 1225, 1424, 309, 260, 261, 1525, 313, 128, 314, 315, - 129, 1221, 527, 586, 509, 1535, 1536, 1537, 130, 529, - 530, 1157, 216, 982, 1433, 1158, 1159, 582, 548, 1465, - 320, 1, 2, 3, 1386, 994, 320, 961, 1413, -2, - 1414, 131, 1415, 320, 132, 1416, 1417, 1418, 1161, 958, - 528, 1023, 306, 307, 320, 959, 133, 528, 528, 1192, - 1168, 1399, 960, 454, 134, 188, 189, 190, 542, 545, - 782, 156, 783, 1021, 784, 1461, 162, 320, 1193, 1391, - 1392, 405, 1202, 1204, 769, 405, 587, 110, 883, 111, - 358, 976, 977, 406, 407, 980, 1486, 406, 407, 320, - 1552, 320, 454, 454, 454, 454, 454, 135, 454, 454, - 454, 410, 408, 320, 454, 136, 1149, 409, 1487, 137, - 1488, 454, 267, 10, 191, 11, 454, 454, 138, 454, - 454, 454, 1489, 454, 454, 1234, 139, 192, 193, 140, - 1532, 1533, 1534, 141, 1535, 1536, 1537, 142, 361, 685, - 488, 1491, 368, 369, 143, 223, 224, 225, 226, 227, - 1143, 228, 229, 230, 1076, 1077, 748, 393, 672, 686, - 1492, 1181, 1495, 676, 677, 678, 194, 195, 1035, 196, - 1036, 144, 682, 683, 684, 197, 1498, 198, 157, 1033, - 1190, 1496, 548, 981, 1160, 328, 378, 1200, 214, 215, - 1054, 993, 1167, 1406, 1058, 1499, 528, 1396, 714, 216, - 158, 528, 528, 528, 320, 163, 1621, 320, 1658, 320, - 528, 528, 528, 454, 454, 320, 509, 320, 154, 152, - 320, 963, 164, 1578, 153, 1622, 1632, 1659, 1669, 6, - 697, -102, 319, -102, 1670, -102, 1671, 326, 1435, 1672, - 1436, 165, 778, 235, 1153, 1154, 1155, 1220, 1052, 517, - 518, 1157, 1158, 1159, 188, 189, 190, 213, 214, 215, - 1555, 531, 532, 533, 1228, 1068, 788, 789, 244, 216, - 266, 188, 189, 190, 793, 302, 794, 304, 410, 408, - 454, 359, 410, 408, 409, 553, 454, 305, 409, 1206, - 782, 1207, 783, -102, 1142, -102, 6, -102, 592, 593, - 1177, 1178, 1179, 1209, 1237, 1238, 648, 312, 649, 380, - 650, 775, 395, 191, 1139, 1140, 803, 379, -280, 1473, - 804, 805, 455, 618, 396, 714, 192, 193, 397, 463, - 191, 1525, 223, 224, 225, 226, 227, 320, 228, 229, - 230, 465, 930, 192, 193, 1235, 1139, 1140, 1226, 800, - 456, 956, 457, 934, 528, 935, 936, 937, 528, 528, - 542, 877, 458, 626, 820, 194, 195, 459, 196, 1139, - 1140, 1393, 460, 470, 197, 838, 198, 1139, 1140, 1457, - 921, 461, 194, 195, 462, 196, 464, 466, 467, 468, - 469, 197, 492, 198, 381, 382, 383, 945, 670, 471, - 474, 946, 223, 224, 225, 226, 227, 475, 228, 229, - 230, 675, 476, 1012, 713, 679, 680, 908, 477, -281, - 497, 199, 478, 479, 480, 200, 745, 504, 481, 482, - 201, 454, 483, 6, 381, 382, 383, 1041, 484, 822, - 485, 1042, 968, 486, 909, 493, 494, 947, 496, 498, - 154, 152, 500, 501, 507, 1455, 153, 931, 6, 1459, - 514, 1612, 1613, 1614, 1530, 1531, 1532, 1533, 1534, 516, - 1535, 1536, 1537, 549, 509, 1406, 956, 537, -206, 552, - 528, 746, 588, 956, 750, 930, 590, 1043, 930, 930, - 930, 820, 820, 820, 591, 606, 820, 328, 610, 611, - 612, 613, 614, 615, 948, 384, 619, 1462, 620, 328, - 800, 956, 621, 956, 624, 548, 956, 646, 647, 673, - 654, 652, 271, -282, 774, 695, 246, 653, 247, 681, - 248, 655, 656, 692, 949, 840, 841, 842, 690, 844, - 699, 846, 700, 847, 848, 384, 701, 703, 950, 708, - 1150, 1044, 908, 951, 908, 707, 716, 765, 952, -213, - 776, 786, 797, 801, 802, 790, 798, 791, 835, 792, - 1674, 795, -373, 839, 1045, 843, 249, 831, 1676, 845, - 832, 833, 850, 879, 112, 882, 820, 881, 1046, 885, - 1522, 1523, 1524, 1047, 886, 378, 887, 888, 1048, 378, - 931, 889, 1525, 931, 931, 931, 890, 891, 893, 910, - 933, 913, 914, 967, 973, 915, 984, 154, 152, 1080, - 956, 969, 1087, 153, 830, 930, -290, 1006, 1010, 930, - 930, 1007, 970, 800, 328, 1479, 1480, 1481, 971, 821, - 250, 822, 972, 823, 1011, 257, 1009, 1013, 1015, 378, - 378, 378, 112, 820, 956, 1016, 1017, 820, 820, 1026, - 542, 1027, 1028, 251, 1029, 1030, 1031, 381, 382, 383, - 810, 1037, 542, 1034, 811, 1038, 1055, 252, 1056, 1060, - 586, 1482, 253, 1078, 1484, 6, 1081, 254, 1082, 824, - 908, 1089, 981, 1180, 582, 993, 1547, 1183, 1191, 956, - 956, 974, 1185, 1184, 6, 978, 979, 1196, 1186, 983, - 1194, 6, 1187, 986, 820, 820, 454, 990, 991, 1188, - 812, 1197, 820, 820, 820, 1212, 1198, 820, 1219, 1008, - 1540, 328, 1199, 1401, 1544, 1530, 1531, 1532, 1533, 1534, - 931, 1535, 1536, 1537, 931, 931, 1213, 542, 1222, 1223, - 378, 1053, 1224, 825, 1241, 1227, 1068, 1236, 1242, 1383, - 1384, 1387, 1087, 988, 989, 1388, 1389, 992, 1398, 1400, - 1408, 1402, 1407, 1403, 112, 1404, 826, 1606, 384, 1410, - 1405, 1411, 1425, 1426, 813, 1610, 1427, 1428, 1429, 1430, - 827, 1615, 1616, 930, 1434, 828, 1431, 519, 1432, 520, - 829, 521, 1454, 1420, 1421, 1458, 1422, 814, 1423, 1467, - 1468, 1463, 1470, 1061, 1464, 1478, 1604, 1065, 1066, 542, - 1069, 815, 112, 1476, 1490, 800, 816, 1493, 257, 1494, - 1501, 817, 1500, 1502, 1634, 820, 1090, 1637, 1497, 1503, - 1135, 1136, 1507, 1541, 1548, 1050, 1145, 522, 1545, 1561, - 1549, 1146, 1550, 1562, 1563, 1553, 1559, 1560, 1564, 1152, - 1565, 1566, 1567, 1156, 1568, 1569, 1574, 1608, 1655, 1577, - 1602, 1605, 204, 1617, 1162, 1163, 1609, 1635, 1611, 1620, - 1624, 1219, 1619, 1219, 1623, 1625, 1664, 1626, 1628, 1629, - 1641, 1636, 1643, 820, 820, 820, 1642, 243, 1644, 1645, - 1646, 1647, 509, 1648, 1649, 1656, 509, 1650, 931, 1651, - 1666, 523, 378, 1654, 1657, 1667, 1668, 265, 271, 271, - 1675, 1677, 1466, 753, 1164, 1477, 1538, 1210, 1165, 1166, - 768, 1618, 1214, 1475, 524, 853, 1215, 1216, 381, 382, - 383, 922, 706, 770, 1182, 923, 1469, 506, 525, 956, - 1229, 0, 0, 526, 0, 67, 303, 1520, 1521, 1522, - 1523, 1524, 956, 0, 0, 0, 0, 0, 0, 0, - 0, 1525, 0, 1203, 1205, 0, 0, 0, 0, 1385, - 0, 0, 988, 989, 0, 0, 992, 0, 0, 0, - 0, 924, 0, 0, 0, 0, 0, 0, 0, 0, - 155, 0, 0, 0, 0, 0, 161, 322, 323, 0, - 0, 0, 166, 167, 168, 169, 170, 0, 956, 206, - 0, 0, 0, 1390, 0, 0, 188, 189, 190, 0, - 0, 0, 0, 0, 0, 350, 0, 1080, 0, 1516, - 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1437, 384, - 0, 0, 0, 0, 360, 925, 0, 1525, 0, 1516, - 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 392, 394, - 1514, 112, 0, 0, 587, 0, 0, 1525, 926, 0, - 112, 0, 509, 509, 509, 191, 378, 0, 0, 378, - 112, 0, 927, 0, 0, 0, 0, 928, 192, 193, - 1409, 0, 0, 1438, 1530, 1531, 1532, 1533, 1534, 0, - 1535, 1536, 1537, 490, 491, 0, 316, 820, 0, 495, - 0, 0, 0, 0, 0, 1514, 0, 0, 0, 0, - 0, 204, 0, 0, 0, 378, 0, 194, 195, 378, - 196, 0, 0, 509, 1523, 1524, 197, 0, 198, 0, - 1087, 0, 1164, 1165, 1166, 1525, 1600, 0, 0, 1001, - 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - 349, 0, 1453, 353, 1526, 1527, 1528, 1529, 357, 0, - 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, 0, - 0, 0, 1631, 265, 1526, 1527, 1528, 1529, 0, 589, - 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, 411, - 0, 378, 0, 0, 509, 0, 0, 0, 0, 0, - 0, 0, 509, 0, 0, 800, 800, 800, 509, 509, - 0, 1196, 0, 0, 0, 0, 0, 0, 0, 0, - 634, 0, 0, 0, 0, 487, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1660, 1661, 1662, - 0, 1663, 502, 503, 0, 0, 0, 1474, 0, 510, - 0, 509, 378, 0, 509, 0, 1513, 0, 1530, 1531, - 1532, 1533, 1534, 0, 1535, 1536, 1537, 0, 1483, 0, - 0, 1485, 0, 0, 209, 210, 211, 212, 213, 214, - 215, 0, 322, 73, 0, 509, 75, 76, 77, 78, - 216, 188, 189, 190, 0, 0, 0, 674, 0, 238, - 0, 0, 541, 509, 0, 0, 1570, 1571, 1572, 1573, - 0, 1575, 0, 1576, 800, 1539, 0, 0, 85, 1543, - 691, 0, 800, 1546, 0, 0, 0, 0, 0, 265, - 0, 0, 0, 0, 0, 239, 1554, 0, 0, 1556, - 1557, 1558, 0, 0, 0, 605, 1409, 0, 0, 0, - 191, 0, 0, 0, 0, 0, 0, 87, 88, 0, - 0, 0, 0, 192, 193, 0, 0, 0, 0, 747, - 749, 0, 0, 0, 93, 0, 0, 0, 1453, 95, - 1453, 1453, 1453, 1453, 1453, 755, 1453, 756, 757, 758, - 759, 760, 761, 0, 0, 763, 0, 0, 0, 0, - 0, 0, 194, 195, 0, 196, 0, 1607, 0, 771, - 772, 197, 0, 198, 0, 0, 0, 0, 780, 502, - 220, 221, 222, 223, 224, 225, 226, 227, 0, 228, - 229, 230, 0, 0, 671, 0, 0, 0, 1452, 0, - 0, 7, 8, 9, 10, 505, 11, 12, 13, 0, - 201, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, - 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, - 1638, 0, 0, 0, 0, 1639, 1640, 209, 210, 211, - 212, 213, 214, 215, 0, 0, 0, 0, 0, 1439, - 0, 0, 0, 216, 1653, 0, 0, 709, 710, 711, - 712, 0, 715, 0, 0, 1440, 0, 0, 0, 0, - 1441, 744, 1453, 0, 0, 1665, 0, 875, 0, 24, - 25, 0, 0, 0, 1673, 27, 0, 0, 0, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 0, 0, 764, 208, 209, - 210, 211, 212, 213, 214, 215, 0, 48, 0, 49, - 0, 0, 0, 1453, 1442, 216, 1453, 0, 0, 1443, - 0, 0, 1444, 0, 964, 0, 0, 55, 1517, 1518, - 1519, 1520, 1521, 1522, 1523, 1524, 0, 0, 796, 0, - 0, 0, 0, 0, 0, 1525, 0, 0, 0, 985, - 0, 0, 1445, 0, 541, 1446, 1447, 1448, 0, 0, - 1449, 0, 1450, 65, 0, 0, 1451, 0, 0, 0, - 0, 0, 1014, 0, 221, 222, 223, 224, 225, 226, - 227, 849, 228, 229, 230, 0, 0, 0, 0, 0, - 0, 0, 854, 855, 856, 857, 858, 859, 860, 861, - 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, - 872, 873, 874, 0, 1506, 878, 1508, 1509, 1510, 1511, - 1512, 0, 1515, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1040, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 0, 228, 229, 230, 944, 0, 0, - 387, 388, 389, 1075, 0, 555, 556, 557, 10, 0, - 11, 558, 559, 1527, 1528, 1529, 0, 560, 1530, 1531, - 1532, 1533, 1534, 0, 1535, 1536, 1537, 1579, 1580, 1581, - 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, - 1592, 1593, 1594, 1595, 1596, 1597, 0, 0, 0, 0, - 110, 0, 111, 561, 0, 0, 0, 0, 0, 191, - 0, 0, 0, 1019, 0, 0, 0, 0, 1176, 562, - 0, 0, 192, 193, 563, 0, 0, 0, 0, 0, - 0, 0, 546, 564, 565, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1211, 0, 0, 0, - 0, 390, 195, 0, 196, 0, 0, 0, 566, 0, - 197, 567, 198, 568, 0, 0, 73, 0, 569, 75, - 76, 77, 78, 570, 0, 0, 571, 0, 0, 0, - 0, 572, 1652, 0, 573, 0, 391, 7, 8, 9, - 10, 0, 11, 12, 13, 14, 1086, 0, 0, 0, - 0, 85, 0, 0, 0, 0, 574, 0, 0, 575, - 576, 0, 0, 0, 577, 0, 578, 0, 239, 0, - 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 541, 15, 0, 0, 0, 16, - 87, 88, 17, 18, 19, 20, 541, 0, 0, 0, - 1169, 21, 0, 941, 942, 22, 23, 93, 0, 0, - 0, 0, 95, 0, 0, 24, 25, 26, 1019, 0, - 0, 27, 0, 1189, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 0, 0, 0, 0, 0, 0, 0, 0, - 46, 0, 47, 48, 0, 49, 0, 0, 0, 0, - 50, 0, 0, 51, 52, 53, 0, 0, 54, 0, - 0, 541, 0, 55, 0, 0, 56, 0, 0, 0, - 57, 0, 0, 0, 0, 58, 1086, 0, 0, 0, - 943, 0, 0, 0, 0, 1075, 0, 0, 59, 0, - 0, 60, 61, 62, 0, 0, 63, 0, 64, 65, - 0, 0, 66, 0, 0, 1243, 1244, 1245, 1246, 1247, - 1248, 1249, 1250, 1251, 1252, 1253, 0, 1254, 1255, 1256, - 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 0, - 0, 1394, 0, 541, 0, 1397, 1266, 1267, 1268, 1269, - 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, - 1280, 1281, 1282, 1283, 1284, 0, 0, 1285, 1286, 1287, - 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, - 1298, 1299, 1300, 1301, 1302, 1303, 0, 1304, 0, 1305, - 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 0, - 1315, 1316, 1317, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 0, 0, 0, 0, 0, 0, 0, 1318, - 0, 216, 0, 0, 0, 0, 1319, 1320, 1321, 1322, - 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, - 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, - 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, - 1353, 1354, 1355, 1356, 1357, 0, 637, 638, 1358, 1359, - 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, - 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1551, - 1379, 1380, 0, 73, 0, 0, 75, 76, 77, 78, - 0, 0, 0, 0, 0, 188, 189, 190, 399, 0, - 0, 73, 400, 0, 75, 76, 77, 78, 79, 0, - 0, 387, 388, 389, 401, 0, 0, 82, 85, 0, - 0, 83, 0, 0, 0, 0, 0, 0, 0, 84, - 0, 0, 0, 0, 0, 239, 85, 0, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 0, - 228, 229, 230, 86, 191, 0, 513, 87, 88, 0, - 0, 0, 0, 0, 0, 0, 639, 192, 193, 0, - 191, 0, 0, 0, 93, 87, 88, 1472, 0, 95, - 0, 89, 1598, 192, 193, 0, 0, 0, 0, 402, - 403, 92, 93, 0, 0, 94, 0, 95, 0, 0, - 0, 0, 640, 0, 0, 0, 194, 195, 0, 196, - 0, 0, 0, 0, 0, 197, 0, 198, 641, 0, - 0, 1627, 390, 195, 0, 196, 0, 0, 0, 0, - 0, 197, 262, 198, 1243, 1244, 1245, 1246, 1247, 1248, - 1249, 1250, 1251, 1252, 1253, 0, 1254, 1255, 1256, 1257, - 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 0, 0, - 385, 0, 0, 0, 1086, 1266, 1267, 1268, 1269, 1270, - 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, - 1281, 1282, 1283, 1284, 0, 0, 1285, 1286, 1287, 1288, - 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, - 1299, 1300, 1301, 1302, 1303, 0, 1304, 0, 1305, 1306, - 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 0, 1315, - 1316, 1317, 0, 0, 0, 0, 0, 0, 0, 0, - 1601, 0, 0, 0, 0, 0, 0, 0, 1318, 0, - 0, 0, 0, 0, 0, 1319, 1320, 1321, 1322, 1323, - 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, - 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, - 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, - 1354, 1355, 1356, 1357, 0, 0, 0, 1358, 1359, 1360, - 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, - 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 0, 1379, - 1380, 7, 8, 9, 10, 0, 11, 12, 13, 171, - 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 0, 0, 0, 0, 0, 0, 0, 15, - 72, 216, 0, 172, 74, 0, 173, 174, 175, 176, - 79, 80, 0, 0, 0, 21, 81, 0, 0, 177, - 23, 0, 0, 83, 0, 0, 0, 0, 0, 24, - 25, 178, 0, 0, 0, 27, 0, 0, 179, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 180, 0, 0, 0, 0, - 0, 0, 0, 0, 46, 0, 47, 48, 0, 49, - 0, 0, 0, 0, 50, 0, 0, 181, 182, 53, - 0, 0, 54, 89, 0, 0, 0, 55, 0, 0, - 56, 90, 91, 92, 183, 0, 0, 94, 0, 184, - 7, 8, 9, 10, 0, 11, 12, 13, 398, 0, - 0, 0, 59, 0, 0, 60, 61, 62, 0, 0, - 63, 0, 64, 65, 0, 0, 66, 0, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 0, - 228, 229, 230, 0, 0, 0, 1022, 0, 15, 399, - 0, 0, 172, 400, 0, 173, 174, 175, 176, 79, - 0, 0, 0, 0, 21, 401, 0, 0, 177, 23, - 0, 0, 83, 0, 0, 0, 0, 0, 24, 25, - 178, 0, 0, 0, 27, 0, 0, 179, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 180, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, - 0, 0, 0, 50, 0, 0, 181, 182, 53, 0, - 0, 54, 89, 0, 0, 0, 55, 0, 0, 56, - 402, 403, 92, 183, 0, 0, 94, 0, 184, 0, - 7, 8, 9, 10, 0, 11, 12, 13, 14, 0, - 0, 59, 159, 0, 60, 61, 62, 0, 0, 63, - 0, 64, 65, 0, 0, 66, 0, 0, 0, 0, - 0, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 0, 0, 0, 0, 0, 0, 0, 0, 15, 216, - 0, 0, 16, 0, 0, 17, 18, 19, 20, 0, - 0, 0, 0, 0, 21, 0, 0, 0, 22, 23, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, - 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, - 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, - 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, - 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, - 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, - 0, 59, 0, 0, 60, 61, 62, 0, 0, 63, - 0, 160, 65, 0, 0, 66, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, - 230, 0, 15, 0, 1633, 0, 16, 0, 0, 17, - 18, 19, 20, 0, 0, 0, 0, 0, 21, 188, - 189, 190, 22, 23, 0, 0, 0, 0, 0, 0, - 0, 0, 24, 25, 26, 0, 0, 0, 27, 0, - 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 46, 0, 47, - 48, 0, 49, 0, 0, 0, 0, 50, 191, 0, - 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, - 55, 192, 193, 56, 0, 0, 0, 57, 7, 8, - 9, 10, 58, 11, 12, 13, 14, 0, 0, 0, - 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, - 62, 0, 0, 63, 0, 64, 65, 351, 0, 66, - 194, 195, 0, 196, 0, 0, 0, 0, 0, 197, - 0, 198, 0, 0, 0, 0, 15, 356, 0, 0, - 16, 0, 0, 17, 18, 19, 20, 0, 0, 0, - 0, 0, 21, 0, 0, 754, 22, 23, 0, 0, - 0, 659, 0, 0, 0, 0, 24, 25, 26, 0, - 0, 0, 27, 0, 0, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 0, 0, 0, 0, 0, 0, 0, - 0, 46, 0, 47, 48, 0, 49, 660, 0, 661, - 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, - 0, 0, 0, 0, 55, 0, 662, 56, 0, 0, - 0, 57, 7, 8, 9, 10, 58, 11, 12, 13, - 14, 0, 0, 0, 0, 0, 0, 0, 0, 59, - 0, 0, 60, 61, 62, 0, 0, 63, 663, 64, - 65, 664, 665, 66, 0, 666, 0, 0, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 0, 0, 0, - 15, 743, 667, 0, 16, 0, 216, 17, 18, 19, - 20, 0, 0, 0, 668, 0, 21, 0, 0, 0, - 22, 23, 0, 0, 0, 0, 0, 0, 669, 0, - 24, 25, 26, 0, 0, 0, 27, 0, 0, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 0, 0, 0, - 0, 0, 0, 0, 0, 46, 0, 47, 48, 0, - 49, 0, 0, 0, 0, 50, 0, 0, 51, 52, - 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, - 0, 56, 0, 0, 0, 57, 7, 8, 9, 10, - 58, 11, 12, 13, 14, 0, 0, 0, 0, 0, - 0, 0, 0, 59, 0, 0, 60, 61, 62, 0, - 0, 63, 0, 64, 65, 0, 0, 66, 0, 0, - 0, 511, 0, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 15, 228, 229, 230, 16, 0, - 0, 17, 18, 19, 20, 0, 0, 0, 0, 0, - 21, 0, 0, 0, 22, 23, 0, 0, 0, 0, - 0, 0, 0, 0, 24, 25, 26, 0, 0, 0, - 27, 0, 0, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 46, - 0, 47, 48, 0, 49, 0, 0, 0, 0, 50, - 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, - 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, - 7, 8, 9, 10, 58, 11, 12, 13, 14, 0, - 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, - 60, 61, 62, 0, 0, 63, 0, 64, 65, 876, - 0, 66, 0, 0, 0, 0, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 0, 0, 0, 15, 0, - 0, 0, 16, 0, 216, 17, 18, 19, 20, 0, - 0, 0, 0, 0, 21, 0, 0, 0, 22, 23, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, - 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, - 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, - 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, - 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, - 12, 13, 14, 1083, 0, 0, 0, 0, 0, 0, - 0, 59, 0, 0, 60, 61, 62, 0, 0, 63, - 0, 64, 65, 0, 0, 66, 0, 0, 0, 1020, - 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 15, 228, 229, 230, 16, 0, 0, 17, - 18, 19, 20, 0, 0, 0, 0, 0, 21, 0, - 0, 0, 22, 23, 0, 0, 0, 0, 0, 0, - 0, 0, 24, 25, 26, 0, 0, 0, 27, 0, - 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 46, 0, 47, - 48, 0, 49, 0, 0, 0, 0, 50, 0, 0, - 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, - 55, 0, 0, 56, 0, 0, 0, 57, 7, 8, - 9, 10, 58, 11, 12, 13, 14, 1471, 0, 0, - 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, - 62, 0, 0, 63, 0, 64, 65, 0, 0, 66, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, - 0, 0, 0, 0, 0, 0, 15, 0, 216, 0, - 16, 0, 0, 17, 18, 19, 20, 0, 0, 0, - 0, 0, 21, 0, 0, 0, 22, 23, 0, 0, - 0, 0, 0, 0, 0, 0, 24, 25, 26, 0, - 0, 0, 27, 0, 0, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 0, 0, 0, 0, 0, 0, 0, - 0, 46, 0, 47, 48, 0, 49, 0, 0, 0, - 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, - 0, 0, 0, 0, 55, 0, 0, 56, 0, 0, - 0, 57, 7, 8, 9, 10, 58, 11, 12, 13, - 14, 0, 0, 0, 0, 0, 0, 0, 0, 59, - 0, 0, 60, 61, 62, 0, 0, 63, 0, 64, - 65, 1599, 1088, 66, 0, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, - 15, 0, 0, 0, 16, 0, 0, 17, 18, 19, - 20, 0, 0, 0, 0, 0, 21, 0, 0, 0, - 22, 23, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 25, 26, 0, 0, 0, 27, 0, 0, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 0, 0, 0, - 0, 0, 0, 0, 0, 46, 0, 47, 48, 0, - 49, 0, 0, 0, 0, 50, 0, 0, 51, 52, - 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, - 0, 56, 0, 0, 0, 57, 7, 8, 9, 10, - 58, 11, 12, 13, 14, 0, 1518, 1519, 1520, 1521, - 1522, 1523, 1524, 59, 0, 0, 60, 61, 62, 0, - 0, 63, 1525, 64, 65, 0, 0, 66, 0, 0, - 0, 0, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 0, 0, 0, 15, 0, 0, 0, 16, 0, - 216, 17, 18, 19, 20, 0, 0, 0, 0, 0, - 21, 0, 0, 0, 22, 23, 0, 0, 0, 0, - 0, 0, 0, 0, 24, 25, 26, 0, 0, 0, - 27, 0, 0, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 46, - 0, 47, 48, 0, 49, 0, 0, 0, 0, 50, - 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, - 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, - 7, 8, 9, 10, 58, 11, 12, 13, 0, 0, - 0, 0, 1504, 0, 0, 1530, 1531, 1532, 1533, 1534, - 0, 1535, 1536, 1537, 0, 63, 0, 64, 65, 0, - 0, 66, 0, 894, 0, 0, 0, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 1439, 228, - 229, 230, 895, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1440, 188, 189, 190, 0, 1441, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, - 0, 0, 0, 0, 27, 0, 0, 0, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 7, 8, 9, 10, 0, 11, - 12, 13, 0, 0, 0, 0, 48, 0, 49, 0, - 0, 0, 0, 1442, 191, 0, 0, 0, 1443, 0, - 632, 1444, 0, 0, 0, 0, 55, 192, 193, 0, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, - 0, 0, 1439, 0, 0, 0, 0, 0, 216, 0, - 0, 1445, 0, 0, 1446, 1447, 1448, 0, 1440, 1449, - 633, 1505, 65, 1441, 0, 1451, 194, 195, 0, 196, - 0, 0, 24, 25, 0, 197, 0, 198, 27, 0, - 0, 0, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 0, 49, 0, 0, 0, 0, 1442, 0, 0, - 0, 0, 1443, 0, 0, 1444, 555, 556, 557, 10, - 55, 11, 558, 559, 0, 0, 0, 0, 852, 0, - 0, 0, 0, 555, 556, 557, 10, 0, 11, 558, - 559, 0, 0, 0, 0, 704, 0, 0, 0, 0, - 0, 0, 0, 1449, 0, 1450, 65, 0, 0, 1451, - 0, 110, 0, 111, 561, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, - 562, 561, 0, 0, 0, 563, 0, 0, 0, 0, - 0, 0, 0, 0, 564, 565, 0, 562, 0, 0, - 0, 0, 563, 209, 210, 211, 212, 213, 214, 215, - 0, 564, 565, 0, 0, 0, 0, 0, 0, 216, - 0, 0, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 566, - 0, 0, 567, 0, 568, 0, 0, 0, 1525, 569, - 0, 0, 0, 0, 570, 0, 566, 571, 0, 567, - 0, 568, 572, 0, 0, 573, 569, 0, 0, 0, - 0, 570, 0, 0, 571, 0, 0, 0, 0, 572, - 0, 0, 573, 0, 0, 0, 0, 574, 0, 0, - 575, 576, 0, 0, 0, 577, 0, 578, 0, 0, - 0, 579, 0, 0, 574, 0, 0, 575, 576, 1092, - 0, 0, 577, 0, 705, 0, 0, 0, 579, 1093, - 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 0, 0, - 0, 0, 0, 0, 188, 189, 190, 1102, 0, 1103, - 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, - 1114, 0, 0, 0, 0, 0, 0, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, - 230, 0, 0, 1115, 0, 0, 1527, 1528, 1529, 637, - 638, 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, - 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, - 211, 212, 213, 214, 215, 0, 192, 193, 0, 0, - 0, 0, 0, 0, 216, 0, 0, 0, 0, 1116, - 0, 399, 0, 0, 73, 400, 0, 75, 76, 77, - 78, 79, 0, 0, 0, 0, 0, 401, 0, 0, - 82, 0, 0, 0, 83, 194, 195, 0, 196, 0, - 0, 0, 84, 0, 197, 0, 198, 0, 0, 85, - 1117, 0, 0, 1118, 0, 1119, 1120, 1121, 1122, 1123, - 1124, 1125, 1126, 1127, 1128, 1129, 86, 1130, 1131, 766, - 767, 1132, 0, 0, 0, 0, 0, 0, 0, 639, - 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, - 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, - 0, 0, 402, 403, 92, 93, 0, 0, 94, 0, - 95, 399, 0, 0, 73, 400, 0, 75, 76, 77, - 78, 79, 0, 0, 0, 0, 0, 401, 0, 0, - 82, 641, 0, 0, 83, 221, 222, 223, 224, 225, - 226, 227, 84, 228, 229, 230, 0, 0, 0, 85, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, - 0, 0, 0, 0, 0, 0, 86, 0, 216, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 0, 639, - 0, 0, 0, 0, 0, 0, 0, 216, 87, 88, - 0, 0, 0, 73, 89, 0, 75, 76, 77, 78, - 0, 0, 402, 403, 92, 93, 0, 0, 94, 238, - 95, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 0, 0, 0, 0, 0, 0, 0, 0, 85, 216, - 0, 641, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 0, 0, 0, 0, 239, 0, 0, 0, 0, - 216, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 0, 0, 0, 0, 0, 0, 0, 87, 88, 216, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, - 0, 0, 0, 0, 93, 0, 0, 0, 216, 95, - 0, 0, 0, 0, 0, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, - 308, 0, 144, 0, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 0, 228, 229, 230, 499, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, - 0, 0, 0, 0, 0, 0, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, - 230, 515, 0, 0, 0, 0, 0, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 0, 228, - 229, 230, 594, 0, 0, 0, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, - 230, 651, 0, 0, 0, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, - 752, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, - 0, 0, 0, 0, 0, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, - 880, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, - 719, 720, 721, 722, 723, 724, 725, 726, 727, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 728, 209, - 210, 211, 212, 213, 214, 215, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 216, 1518, 1519, 1520, 1521, - 1522, 1523, 1524, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1525, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, - 230, 962, 0, 0, 0, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, - 1018, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1525, 0, 0, - 0, 0, 1412, 0, 0, 0, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, - 230, 0, 0, 0, 0, 729, 730, 731, 732, 733, - 734, 735, 736, 737, 738, 739, 0, 740, 741, 742, - 601, 0, 0, 659, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 0, 228, 229, 230, 0, 0, 0, - 0, 1528, 1529, 0, 0, 1530, 1531, 1532, 1533, 1534, - 0, 1535, 1536, 1537, 110, 0, 111, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 413, 660, - 0, 661, 0, 0, 0, 0, 0, 414, 415, 416, - 417, 0, 0, 0, 0, 0, 0, 0, 662, 0, - 419, 420, 421, 422, 0, 601, 0, 0, 0, 0, - 0, 0, 0, 535, 0, 0, 0, 1529, 0, 0, - 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, 0, - 663, 0, 0, 664, 665, 0, 0, 666, 432, 0, - 0, 896, 897, 898, 0, 0, 0, 0, 0, 437, - 0, 0, 0, 413, 667, 0, 438, 0, 0, 0, - 440, 441, 414, 415, 416, 417, 668, 0, 0, 0, - 0, 0, 444, 0, 445, 419, 534, 421, 422, 0, - 669, 0, 0, 0, 0, 0, 73, 0, 535, 75, - 76, 77, 78, 899, 900, 896, 897, 898, 0, 0, - 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 432, 84, 0, 0, 0, 0, 0, - 0, 85, 0, 0, 437, 0, 0, 0, 0, 0, - 0, 438, 0, 0, 0, 0, 441, 0, 86, 0, - 73, 0, 0, 75, 76, 77, 78, 444, 0, 445, - 0, 0, 0, 70, 71, 0, 82, 0, 0, 0, - 87, 88, 0, 0, 0, 0, 0, 0, 84, 0, - 0, 0, 0, 0, 901, 85, 0, 93, 0, 0, - 94, 902, 95, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 86, 0, 72, 0, 0, 73, 74, 0, - 75, 76, 77, 78, 79, 80, 0, 0, 0, 0, - 81, 0, 0, 82, 87, 88, 0, 83, 70, 71, - 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, - 0, 93, 85, 0, 94, 0, 95, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, - 0, 70, 0, 0, 0, 0, 0, 0, 0, 72, - 0, 0, 73, 74, 0, 75, 76, 77, 78, 79, - 0, 87, 88, 0, 0, 81, 0, 89, 82, 0, - 0, 0, 83, 0, 0, 90, 91, 92, 93, 0, - 84, 94, 72, 95, 0, 73, 74, 85, 75, 76, - 77, 78, 79, 777, 0, 0, 0, 0, 81, 0, - 0, 82, 0, 0, 86, 83, 145, 0, 0, 0, - 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, - 85, 0, 0, 0, 0, 0, 87, 88, 0, 0, - 0, 0, 89, 0, 0, 0, 0, 86, 0, 145, - 90, 91, 92, 93, 0, 0, 94, 146, 95, 0, - 73, 147, 0, 75, 76, 77, 78, 79, 965, 87, - 88, 0, 0, 148, 0, 89, 82, 0, 0, 0, - 83, 0, 0, 90, 91, 92, 93, 0, 84, 94, - 146, 95, 0, 73, 147, 85, 75, 76, 77, 78, - 79, 0, 0, 0, 0, 0, 148, 0, 0, 82, - 0, 0, 86, 83, 70, 0, 0, 0, 0, 0, - 0, 84, 0, 0, 0, 0, 0, 0, 85, 0, - 0, 188, 189, 190, 87, 88, 0, 0, 0, 0, - 89, 0, 0, 0, 0, 86, 0, 0, 149, 150, - 92, 93, 0, 0, 94, 72, 95, 0, 73, 74, - 0, 75, 76, 77, 78, 79, 0, 87, 88, 0, - 0, 81, 0, 89, 82, 0, 0, 0, 83, 0, - 0, 149, 150, 92, 93, 0, 84, 94, 0, 95, - 191, 0, 0, 85, 0, 0, 0, 0, 188, 189, - 190, 0, 0, 192, 193, 0, 0, 0, 0, 0, - 86, 0, 0, 188, 189, 190, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 188, 189, - 190, 0, 87, 88, 0, 0, 0, 0, 89, 0, - 0, 0, 194, 998, 999, 1000, 90, 91, 92, 93, - 0, 197, 94, 198, 95, 0, 0, 191, 0, 0, - 0, 0, 0, 0, 1001, 0, 0, 0, 0, 1002, - 192, 193, 191, 0, 0, 0, 0, 0, 73, 0, - 0, 75, 76, 77, 78, 192, 193, 191, 0, 0, - 188, 189, 190, 0, 0, 1039, 0, 0, 0, 0, - 192, 193, 73, 0, 0, 75, 76, 77, 78, 194, - 195, 0, 196, 85, 0, 0, 0, 0, 197, 0, - 198, 0, 0, 0, 194, 195, 0, 196, 0, 0, - 239, 1001, 0, 197, 0, 198, 1170, 85, 0, 194, - 195, 0, 196, 0, 0, 0, 1001, 0, 197, 191, - 198, 1172, 87, 88, 239, 0, 0, 0, 0, 0, - 0, 1001, 192, 193, 0, 0, 1174, 0, 0, 93, - 0, 0, 0, 0, 95, 0, 87, 88, 73, 0, - 0, 75, 76, 77, 78, 0, 0, 0, 0, 0, - 0, 0, 0, 93, 0, 0, 0, 157, 95, 0, - 0, 194, 195, 0, 196, 0, 0, 0, 0, 0, - 197, 0, 198, 85, 0, 413, 0, 0, 0, 0, - 0, 158, 0, 0, 414, 415, 416, 417, 0, 0, - 239, 0, 0, 0, 0, 0, 0, 419, 534, 421, - 422, 0, 0, 0, 0, 424, 0, 0, 0, 0, - 535, 0, 87, 88, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, - 0, 0, 0, 0, 95, 432, 0, 0, 0, 412, - 413, 0, 0, 0, 0, 0, 437, 0, 0, 414, - 415, 416, 417, 438, 0, 0, 0, 164, 441, 0, - 418, 0, 419, 420, 421, 422, 423, 0, 443, 444, - 424, 445, 0, 0, 0, 425, 0, 0, 0, 0, - 413, 0, 0, 0, 0, 0, -161, 0, 0, 414, - 415, 416, 417, 0, 426, 427, 428, 429, 430, 431, - 432, 433, 419, 534, 421, 422, 0, 0, 434, 435, - 436, 437, 0, 0, 0, 535, 0, 0, 438, 439, - 413, 0, 440, 441, 0, 0, 0, 442, 0, 414, - 415, 416, 417, 443, 444, 0, 445, 413, 0, 0, - 432, 608, 419, 420, 421, 422, 414, 415, 416, 417, - 424, 437, 0, 0, 0, 535, 0, 0, 438, 419, - 534, 421, 422, 441, 0, 0, 0, 0, 0, 0, - 0, 0, 535, 0, 444, 0, 445, 0, 0, 0, - 432, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 437, 0, 0, 0, 0, 0, 432, 438, 0, - 0, 0, 440, 441, 0, 0, 0, 0, 437, 0, - 0, 0, 0, 443, 444, 438, 445, 0, 0, 0, - 441, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 444, 0, 445 -}; - -static const yytype_int16 yycheck[] = -{ - 1, 97, 397, 80, 64, 115, 420, 117, 118, 119, - 120, 121, 440, 123, 440, 125, 397, 127, 46, 46, - 374, 506, 1083, 80, 46, 550, 912, 566, 549, 15, - 266, 266, 10, 13, 144, 13, 934, 768, 396, 86, - 87, 88, 685, 266, 266, 15, 93, 157, 158, 6, - 48, 8, 50, 157, 164, 165, 831, 15, 681, 413, - 414, 415, 416, 417, 65, 419, 420, 421, 62, 967, - 15, 425, 175, 176, 15, 179, 17, 921, 432, 160, - 924, 925, 926, 437, 438, 82, 440, 441, 442, 537, - 444, 445, 617, 0, 175, 96, 97, 10, 11, 12, - 160, 507, 34, 48, 174, 50, 48, 48, 50, 50, - 48, 34, 50, 114, 115, 174, 117, 118, 119, 120, - 121, 157, 123, 82, 125, 6, 127, 8, 48, 34, - 50, 174, 15, 180, 181, 182, 183, 233, 234, 82, - 176, 135, 157, 144, 260, 261, 48, 48, 50, 50, - 48, 174, 50, 249, 250, 251, 157, 158, 539, 156, - 158, 176, 159, 164, 165, 48, 34, 50, 160, 229, - 813, 814, 174, 919, 817, 570, 998, 999, 1000, 954, - 534, 535, 48, 175, 50, 157, 34, 157, 82, 169, - 176, 169, 239, 157, 552, 305, 160, 156, 174, 157, - 159, 947, 203, 949, 176, 48, 952, 50, 121, 165, - 249, 250, 251, 156, 449, 5, 159, 1061, 156, 176, - 64, 1065, 1066, 164, 955, 160, 449, 449, 169, 754, - 174, 175, 233, 234, 174, 177, 159, 156, 266, 266, - 175, 173, 174, 175, 266, 156, 159, 601, 249, 250, - 251, 174, 175, 254, 779, 174, 165, 177, 157, 798, - 175, 176, 156, 174, 907, 159, 174, 268, 173, 174, - 175, 48, 116, 50, 174, 177, 177, 176, 122, 177, - 124, 157, 126, 174, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 176, 169, 170, 171, 305, 173, 174, 175, 175, 176, - 1056, 177, 156, 103, 104, 34, 160, 174, 162, 163, - 174, 1052, 361, 718, 325, 173, 174, 175, 174, 368, - 369, 974, 34, 818, 177, 978, 979, 718, 385, 1237, - 157, 153, 154, 155, 1090, 830, 157, 795, 1170, 0, - 1172, 174, 1174, 157, 174, 1177, 1178, 1179, 981, 176, - 361, 882, 152, 153, 157, 176, 174, 368, 369, 157, - 993, 1146, 176, 374, 174, 10, 11, 12, 379, 380, - 156, 165, 158, 176, 160, 1229, 165, 157, 176, 1135, - 1136, 626, 1035, 1036, 630, 630, 397, 48, 752, 50, - 244, 1044, 1045, 626, 626, 1048, 176, 630, 630, 157, - 1471, 157, 413, 414, 415, 416, 417, 174, 419, 420, - 421, 449, 449, 157, 425, 174, 965, 449, 176, 174, - 176, 432, 158, 6, 69, 8, 437, 438, 174, 440, - 441, 442, 176, 444, 445, 1068, 174, 82, 83, 174, - 169, 170, 171, 174, 173, 174, 175, 174, 248, 536, - 304, 157, 252, 253, 174, 167, 168, 169, 170, 171, - 955, 173, 174, 175, 69, 70, 592, 593, 517, 536, - 176, 1006, 157, 522, 523, 524, 121, 122, 900, 124, - 902, 174, 531, 532, 533, 130, 157, 132, 174, 894, - 1025, 176, 549, 175, 176, 506, 507, 1032, 23, 24, - 916, 175, 176, 1156, 920, 176, 517, 1140, 578, 34, - 174, 522, 523, 524, 157, 174, 157, 157, 157, 157, - 531, 532, 533, 534, 535, 157, 537, 157, 566, 566, - 157, 176, 174, 176, 566, 176, 176, 176, 176, 550, - 551, 156, 176, 158, 176, 160, 176, 160, 1202, 176, - 1204, 174, 639, 174, 970, 971, 972, 1052, 1454, 359, - 360, 1214, 1215, 1216, 10, 11, 12, 22, 23, 24, - 1478, 371, 372, 373, 174, 175, 646, 647, 174, 34, - 174, 10, 11, 12, 654, 174, 656, 174, 626, 626, - 601, 169, 630, 630, 626, 395, 607, 174, 630, 1037, - 156, 1037, 158, 156, 160, 158, 617, 160, 408, 409, - 122, 123, 124, 1037, 156, 157, 470, 174, 472, 156, - 474, 174, 49, 69, 174, 175, 675, 175, 175, 1385, - 679, 680, 177, 433, 157, 705, 82, 83, 174, 166, - 69, 34, 167, 168, 169, 170, 171, 157, 173, 174, - 175, 166, 778, 82, 83, 1071, 174, 175, 176, 670, - 176, 787, 176, 156, 675, 158, 159, 160, 679, 680, - 681, 741, 176, 1037, 685, 121, 122, 176, 124, 174, - 175, 176, 176, 157, 130, 696, 132, 174, 175, 176, - 777, 176, 121, 122, 176, 124, 176, 176, 176, 176, - 176, 130, 166, 132, 10, 11, 12, 13, 508, 176, - 157, 17, 167, 168, 169, 170, 171, 176, 173, 174, - 175, 521, 176, 843, 578, 525, 526, 765, 176, 175, - 166, 160, 176, 176, 176, 164, 590, 15, 176, 176, - 169, 752, 176, 754, 10, 11, 12, 13, 176, 15, - 176, 17, 801, 176, 765, 176, 176, 63, 176, 176, - 798, 798, 176, 176, 174, 1223, 798, 778, 779, 1227, - 176, 1556, 1557, 1558, 167, 168, 169, 170, 171, 176, - 173, 174, 175, 159, 795, 1438, 912, 176, 176, 159, - 801, 591, 174, 919, 594, 921, 174, 63, 924, 925, - 926, 812, 813, 814, 176, 159, 817, 818, 174, 174, - 174, 174, 174, 174, 120, 121, 159, 1233, 159, 830, - 831, 947, 159, 949, 174, 882, 952, 174, 174, 169, - 174, 176, 843, 175, 634, 82, 13, 176, 15, 175, - 17, 176, 174, 177, 150, 699, 700, 701, 179, 703, - 174, 705, 165, 707, 708, 121, 165, 165, 164, 174, - 966, 127, 900, 169, 902, 165, 176, 165, 174, 176, - 174, 158, 174, 673, 674, 176, 34, 176, 159, 176, - 1665, 176, 156, 49, 150, 174, 63, 687, 1673, 174, - 690, 691, 176, 176, 694, 159, 907, 176, 164, 156, - 22, 23, 24, 169, 157, 916, 157, 157, 174, 920, - 921, 157, 34, 924, 925, 926, 157, 157, 156, 174, - 174, 158, 158, 156, 169, 160, 169, 965, 965, 940, - 1056, 179, 943, 965, 686, 1061, 175, 156, 166, 1065, - 1066, 157, 174, 954, 955, 1403, 1404, 1405, 174, 13, - 127, 15, 174, 17, 166, 966, 176, 166, 176, 970, - 971, 972, 762, 974, 1090, 166, 176, 978, 979, 10, - 981, 10, 10, 150, 10, 10, 10, 10, 11, 12, - 13, 166, 993, 158, 17, 157, 176, 164, 169, 169, - 1395, 1407, 169, 177, 1410, 1006, 158, 174, 158, 63, - 1038, 169, 175, 15, 1395, 175, 1464, 174, 157, 1135, - 1136, 811, 176, 174, 1025, 815, 816, 1028, 174, 819, - 157, 1032, 176, 823, 1035, 1036, 1037, 827, 828, 174, - 63, 157, 1043, 1044, 1045, 160, 157, 1048, 1049, 839, - 1456, 1052, 157, 1149, 1460, 167, 168, 169, 170, 171, - 1061, 173, 174, 175, 1065, 1066, 169, 1068, 158, 176, - 1071, 915, 174, 127, 158, 176, 175, 177, 158, 177, - 157, 10, 1083, 825, 826, 176, 179, 829, 157, 176, - 179, 177, 174, 176, 884, 176, 150, 1545, 121, 174, - 176, 179, 10, 10, 127, 1553, 158, 10, 176, 10, - 164, 1559, 1560, 1229, 158, 169, 10, 13, 10, 15, - 174, 17, 157, 1183, 1184, 174, 1186, 150, 1188, 1239, - 1240, 179, 177, 923, 176, 156, 1542, 927, 928, 1140, - 930, 164, 932, 179, 176, 1146, 169, 157, 1149, 158, - 165, 174, 174, 165, 1602, 1156, 946, 1605, 176, 165, - 950, 951, 165, 174, 177, 907, 956, 63, 176, 158, - 177, 961, 176, 10, 158, 176, 176, 176, 10, 969, - 10, 158, 158, 973, 10, 158, 174, 15, 1636, 176, - 176, 176, 65, 157, 984, 985, 177, 1603, 177, 157, - 166, 1202, 176, 1204, 176, 166, 1654, 166, 176, 166, - 10, 176, 158, 1214, 1215, 1216, 176, 90, 10, 10, - 158, 174, 1223, 174, 174, 158, 1227, 176, 1229, 174, - 158, 127, 1233, 176, 176, 10, 158, 110, 1239, 1240, - 176, 158, 1238, 607, 986, 1398, 1454, 1038, 990, 991, - 630, 1562, 1042, 1395, 150, 718, 1046, 1047, 10, 11, - 12, 13, 570, 630, 1007, 17, 1358, 324, 164, 1385, - 1060, -1, -1, 169, -1, 2, 149, 20, 21, 22, - 23, 24, 1398, -1, -1, -1, -1, -1, -1, -1, - -1, 34, -1, 1035, 1036, -1, -1, -1, -1, 1089, - -1, -1, 1044, 1045, -1, -1, 1048, -1, -1, -1, - -1, 63, -1, -1, -1, -1, -1, -1, -1, -1, - 47, -1, -1, -1, -1, -1, 53, 200, 201, -1, - -1, -1, 59, 60, 61, 62, 63, -1, 1454, 66, - -1, -1, -1, 1133, -1, -1, 10, 11, 12, -1, - -1, -1, -1, -1, -1, 228, -1, 1358, -1, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 1212, 121, - -1, -1, -1, -1, 247, 127, -1, 34, -1, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 261, 262, - 1450, 1181, -1, -1, 1395, -1, -1, 34, 150, -1, - 1190, -1, 1403, 1404, 1405, 69, 1407, -1, -1, 1410, - 1200, -1, 164, -1, -1, -1, -1, 169, 82, 83, - 1162, -1, -1, 1213, 167, 168, 169, 170, 171, -1, - 173, 174, 175, 306, 307, -1, 163, 1438, -1, 312, - -1, -1, -1, -1, -1, 1505, -1, -1, -1, -1, - -1, 324, -1, -1, -1, 1456, -1, 121, 122, 1460, - 124, -1, -1, 1464, 23, 24, 130, -1, 132, -1, - 1471, -1, 1214, 1215, 1216, 34, 1536, -1, -1, 143, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, -1, 1217, 230, 161, 162, 163, 164, 235, -1, - 167, 168, 169, 170, 171, -1, 173, 174, 175, -1, - -1, -1, 159, 396, 161, 162, 163, 164, -1, 402, - 167, 168, 169, 170, 171, -1, 173, 174, 175, 266, - -1, 1542, -1, -1, 1545, -1, -1, -1, -1, -1, - -1, -1, 1553, -1, -1, 1556, 1557, 1558, 1559, 1560, - -1, 1562, -1, -1, -1, -1, -1, -1, -1, -1, - 443, -1, -1, -1, -1, 302, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1647, 1648, 1649, - -1, 1651, 319, 320, -1, -1, -1, 1387, -1, 326, - -1, 1602, 1603, -1, 1605, -1, 1450, -1, 167, 168, - 169, 170, 171, -1, 173, 174, 175, -1, 1408, -1, - -1, 1411, -1, -1, 18, 19, 20, 21, 22, 23, - 24, -1, 505, 55, -1, 1636, 58, 59, 60, 61, - 34, 10, 11, 12, -1, -1, -1, 520, -1, 71, - -1, -1, 379, 1654, -1, -1, 1500, 1501, 1502, 1503, - -1, 1505, -1, 1507, 1665, 1455, -1, -1, 90, 1459, - 543, -1, 1673, 1463, -1, -1, -1, -1, -1, 552, - -1, -1, -1, -1, -1, 107, 1476, -1, -1, 1479, - 1480, 1481, -1, -1, -1, 422, 1438, -1, -1, -1, - 69, -1, -1, -1, -1, -1, -1, 129, 130, -1, - -1, -1, -1, 82, 83, -1, -1, -1, -1, 592, - 593, -1, -1, -1, 146, -1, -1, -1, 1443, 151, - 1445, 1446, 1447, 1448, 1449, 608, 1451, 610, 611, 612, - 613, 614, 615, -1, -1, 618, -1, -1, -1, -1, - -1, -1, 121, 122, -1, 124, -1, 1547, -1, 632, - 633, 130, -1, 132, -1, -1, -1, -1, 641, 496, - 164, 165, 166, 167, 168, 169, 170, 171, -1, 173, - 174, 175, -1, -1, 511, -1, -1, -1, 1217, -1, - -1, 3, 4, 5, 6, 164, 8, 9, 10, -1, - 169, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, - 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, - 1610, -1, -1, -1, -1, 1615, 1616, 18, 19, 20, - 21, 22, 23, 24, -1, -1, -1, -1, -1, 51, - -1, -1, -1, 34, 1634, -1, -1, 574, 575, 576, - 577, -1, 579, -1, -1, 67, -1, -1, -1, -1, - 72, 588, 1577, -1, -1, 1655, -1, 740, -1, 81, - 82, -1, -1, -1, 1664, 87, -1, -1, -1, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, -1, -1, 624, 17, 18, - 19, 20, 21, 22, 23, 24, -1, 119, -1, 121, - -1, -1, -1, 1628, 126, 34, 1631, -1, -1, 131, - -1, -1, 134, -1, 797, -1, -1, 139, 17, 18, - 19, 20, 21, 22, 23, 24, -1, -1, 665, -1, - -1, -1, -1, -1, -1, 34, -1, -1, -1, 822, - -1, -1, 164, -1, 681, 167, 168, 169, -1, -1, - 172, -1, 174, 175, -1, -1, 178, -1, -1, -1, - -1, -1, 845, -1, 165, 166, 167, 168, 169, 170, - 171, 708, 173, 174, 175, -1, -1, -1, -1, -1, - -1, -1, 719, 720, 721, 722, 723, 724, 725, 726, - 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, - 737, 738, 739, -1, 1443, 742, 1445, 1446, 1447, 1448, - 1449, -1, 1451, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 905, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, -1, 173, 174, 175, 784, -1, -1, - 10, 11, 12, 936, -1, 3, 4, 5, 6, -1, - 8, 9, 10, 162, 163, 164, -1, 15, 167, 168, - 169, 170, 171, -1, 173, 174, 175, 1516, 1517, 1518, - 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, - 1529, 1530, 1531, 1532, 1533, 1534, -1, -1, -1, -1, - 48, -1, 50, 51, -1, -1, -1, -1, -1, 69, - -1, -1, -1, 850, -1, -1, -1, -1, 1001, 67, - -1, -1, 82, 83, 72, -1, -1, -1, -1, -1, - -1, -1, 11, 81, 82, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1039, -1, -1, -1, - -1, 121, 122, -1, 124, -1, -1, -1, 116, -1, - 130, 119, 132, 121, -1, -1, 55, -1, 126, 58, - 59, 60, 61, 131, -1, -1, 134, -1, -1, -1, - -1, 139, 1631, -1, 142, -1, 156, 3, 4, 5, - 6, -1, 8, 9, 10, 11, 943, -1, -1, -1, - -1, 90, -1, -1, -1, -1, 164, -1, -1, 167, - 168, -1, -1, -1, 172, -1, 174, -1, 107, -1, - 178, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 981, 51, -1, -1, -1, 55, - 129, 130, 58, 59, 60, 61, 993, -1, -1, -1, - 997, 67, -1, 69, 70, 71, 72, 146, -1, -1, - -1, -1, 151, -1, -1, 81, 82, 83, 1015, -1, - -1, 87, -1, 1020, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, -1, -1, -1, -1, -1, -1, -1, -1, - 116, -1, 118, 119, -1, 121, -1, -1, -1, -1, - 126, -1, -1, 129, 130, 131, -1, -1, 134, -1, - -1, 1068, -1, 139, -1, -1, 142, -1, -1, -1, - 146, -1, -1, -1, -1, 151, 1083, -1, -1, -1, - 156, -1, -1, -1, -1, 1238, -1, -1, 164, -1, - -1, 167, 168, 169, -1, -1, 172, -1, 174, 175, - -1, -1, 178, -1, -1, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, -1, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, - -1, 1138, -1, 1140, -1, 1142, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, -1, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 16, 17, 18, 19, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, -1, -1, 107, - -1, 34, -1, -1, -1, -1, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, -1, 10, 11, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, -1, 55, -1, -1, 58, 59, 60, 61, - -1, -1, -1, -1, -1, 10, 11, 12, 52, -1, - -1, 55, 56, -1, 58, 59, 60, 61, 62, -1, - -1, 10, 11, 12, 68, -1, -1, 71, 90, -1, - -1, 75, -1, -1, -1, -1, -1, -1, -1, 83, - -1, -1, -1, -1, -1, 107, 90, -1, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, -1, - 173, 174, 175, 107, 69, -1, 179, 129, 130, -1, - -1, -1, -1, -1, -1, -1, 120, 82, 83, -1, - 69, -1, -1, -1, 146, 129, 130, 1384, -1, 151, - -1, 135, 1535, 82, 83, -1, -1, -1, -1, 143, - 144, 145, 146, -1, -1, 149, -1, 151, -1, -1, - -1, -1, 156, -1, -1, -1, 121, 122, -1, 124, - -1, -1, -1, -1, -1, 130, -1, 132, 172, -1, - -1, 1574, 121, 122, -1, 124, -1, -1, -1, -1, - -1, 130, 147, 132, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, -1, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, - 159, -1, -1, -1, 1471, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, -1, -1, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, -1, 88, - 89, 90, -1, -1, -1, -1, -1, -1, -1, -1, - 1537, -1, -1, -1, -1, -1, -1, -1, 107, -1, - -1, -1, -1, -1, -1, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, -1, -1, -1, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, -1, 178, - 179, 3, 4, 5, 6, -1, 8, 9, 10, 11, - 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 16, 17, 18, 19, 20, 21, 22, - 23, 24, -1, -1, -1, -1, -1, -1, -1, 51, - 52, 34, -1, 55, 56, -1, 58, 59, 60, 61, - 62, 63, -1, -1, -1, 67, 68, -1, -1, 71, - 72, -1, -1, 75, -1, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, -1, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, -1, -1, -1, -1, - -1, -1, -1, -1, 116, -1, 118, 119, -1, 121, - -1, -1, -1, -1, 126, -1, -1, 129, 130, 131, - -1, -1, 134, 135, -1, -1, -1, 139, -1, -1, - 142, 143, 144, 145, 146, -1, -1, 149, -1, 151, - 3, 4, 5, 6, -1, 8, 9, 10, 11, -1, - -1, -1, 164, -1, -1, 167, 168, 169, -1, -1, - 172, -1, 174, 175, -1, -1, 178, -1, 161, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, -1, - 173, 174, 175, -1, -1, -1, 179, -1, 51, 52, - -1, -1, 55, 56, -1, 58, 59, 60, 61, 62, - -1, -1, -1, -1, 67, 68, -1, -1, 71, 72, - -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, -1, -1, -1, -1, -1, - -1, -1, -1, 116, -1, 118, 119, -1, 121, -1, - -1, -1, -1, 126, -1, -1, 129, 130, 131, -1, - -1, 134, 135, -1, -1, -1, 139, -1, -1, 142, - 143, 144, 145, 146, -1, -1, 149, -1, 151, -1, - 3, 4, 5, 6, -1, 8, 9, 10, 11, -1, - -1, 164, 15, -1, 167, 168, 169, -1, -1, 172, - -1, 174, 175, -1, -1, 178, -1, -1, -1, -1, - -1, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, -1, -1, -1, 51, 34, - -1, -1, 55, -1, -1, 58, 59, 60, 61, -1, - -1, -1, -1, -1, 67, -1, -1, -1, 71, 72, - -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, -1, -1, -1, -1, -1, - -1, -1, -1, 116, -1, 118, 119, -1, 121, -1, - -1, -1, -1, 126, -1, -1, 129, 130, 131, -1, - -1, 134, -1, -1, -1, -1, 139, -1, -1, 142, - -1, -1, -1, 146, 3, 4, 5, 6, 151, 8, - 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, - -1, 164, -1, -1, 167, 168, 169, -1, -1, 172, - -1, 174, 175, -1, -1, 178, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, - 175, -1, 51, -1, 179, -1, 55, -1, -1, 58, - 59, 60, 61, -1, -1, -1, -1, -1, 67, 10, - 11, 12, 71, 72, -1, -1, -1, -1, -1, -1, - -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, - -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, -1, - -1, -1, -1, -1, -1, -1, -1, 116, -1, 118, - 119, -1, 121, -1, -1, -1, -1, 126, 69, -1, - 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, - 139, 82, 83, 142, -1, -1, -1, 146, 3, 4, - 5, 6, 151, 8, 9, 10, 11, -1, -1, -1, - -1, -1, -1, -1, -1, 164, -1, -1, 167, 168, - 169, -1, -1, 172, -1, 174, 175, 176, -1, 178, - 121, 122, -1, 124, -1, -1, -1, -1, -1, 130, - -1, 132, -1, -1, -1, -1, 51, 52, -1, -1, - 55, -1, -1, 58, 59, 60, 61, -1, -1, -1, - -1, -1, 67, -1, -1, 156, 71, 72, -1, -1, - -1, 17, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, -1, -1, -1, -1, -1, -1, -1, - -1, 116, -1, 118, 119, -1, 121, 63, -1, 65, - -1, 126, -1, -1, 129, 130, 131, -1, -1, 134, - -1, -1, -1, -1, 139, -1, 82, 142, -1, -1, - -1, 146, 3, 4, 5, 6, 151, 8, 9, 10, - 11, -1, -1, -1, -1, -1, -1, -1, -1, 164, - -1, -1, 167, 168, 169, -1, -1, 172, 114, 174, - 175, 117, 118, 178, -1, 121, -1, -1, 16, 17, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, - 51, 52, 138, -1, 55, -1, 34, 58, 59, 60, - 61, -1, -1, -1, 150, -1, 67, -1, -1, -1, - 71, 72, -1, -1, -1, -1, -1, -1, 164, -1, - 81, 82, 83, -1, -1, -1, 87, -1, -1, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, -1, -1, -1, - -1, -1, -1, -1, -1, 116, -1, 118, 119, -1, - 121, -1, -1, -1, -1, 126, -1, -1, 129, 130, - 131, -1, -1, 134, -1, -1, -1, -1, 139, -1, - -1, 142, -1, -1, -1, 146, 3, 4, 5, 6, - 151, 8, 9, 10, 11, -1, -1, -1, -1, -1, - -1, -1, -1, 164, -1, -1, 167, 168, 169, -1, - -1, 172, -1, 174, 175, -1, -1, 178, -1, -1, - -1, 159, -1, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 51, 173, 174, 175, 55, -1, - -1, 58, 59, 60, 61, -1, -1, -1, -1, -1, - 67, -1, -1, -1, 71, 72, -1, -1, -1, -1, - -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, - 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, -1, -1, -1, -1, -1, -1, -1, -1, 116, - -1, 118, 119, -1, 121, -1, -1, -1, -1, 126, - -1, -1, 129, 130, 131, -1, -1, 134, -1, -1, - -1, -1, 139, -1, -1, 142, -1, -1, -1, 146, - 3, 4, 5, 6, 151, 8, 9, 10, 11, -1, - -1, -1, -1, -1, -1, -1, -1, 164, -1, -1, - 167, 168, 169, -1, -1, 172, -1, 174, 175, 176, - -1, 178, -1, -1, -1, -1, 16, 17, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, 51, -1, - -1, -1, 55, -1, 34, 58, 59, 60, 61, -1, - -1, -1, -1, -1, 67, -1, -1, -1, 71, 72, - -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, - 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, -1, -1, -1, -1, -1, - -1, -1, -1, 116, -1, 118, 119, -1, 121, -1, - -1, -1, -1, 126, -1, -1, 129, 130, 131, -1, - -1, 134, -1, -1, -1, -1, 139, -1, -1, 142, - -1, -1, -1, 146, 3, 4, 5, 6, 151, 8, - 9, 10, 11, 156, -1, -1, -1, -1, -1, -1, - -1, 164, -1, -1, 167, 168, 169, -1, -1, 172, - -1, 174, 175, -1, -1, 178, -1, -1, -1, 159, - -1, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 51, 173, 174, 175, 55, -1, -1, 58, - 59, 60, 61, -1, -1, -1, -1, -1, 67, -1, - -1, -1, 71, 72, -1, -1, -1, -1, -1, -1, - -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, - -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, -1, - -1, -1, -1, -1, -1, -1, -1, 116, -1, 118, - 119, -1, 121, -1, -1, -1, -1, 126, -1, -1, - 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, - 139, -1, -1, 142, -1, -1, -1, 146, 3, 4, - 5, 6, 151, 8, 9, 10, 11, 156, -1, -1, - -1, -1, -1, -1, -1, 164, -1, -1, 167, 168, - 169, -1, -1, 172, -1, 174, 175, -1, -1, 178, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, 51, -1, 34, -1, - 55, -1, -1, 58, 59, 60, 61, -1, -1, -1, - -1, -1, 67, -1, -1, -1, 71, 72, -1, -1, - -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, - -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, -1, -1, -1, -1, -1, -1, -1, - -1, 116, -1, 118, 119, -1, 121, -1, -1, -1, - -1, 126, -1, -1, 129, 130, 131, -1, -1, 134, - -1, -1, -1, -1, 139, -1, -1, 142, -1, -1, - -1, 146, 3, 4, 5, 6, 151, 8, 9, 10, - 11, -1, -1, -1, -1, -1, -1, -1, -1, 164, - -1, -1, 167, 168, 169, -1, -1, 172, -1, 174, - 175, 176, 158, 178, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 51, -1, -1, -1, 55, -1, -1, 58, 59, 60, - 61, -1, -1, -1, -1, -1, 67, -1, -1, -1, - 71, 72, -1, -1, -1, -1, -1, -1, -1, -1, - 81, 82, 83, -1, -1, -1, 87, -1, -1, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, -1, -1, -1, - -1, -1, -1, -1, -1, 116, -1, 118, 119, -1, - 121, -1, -1, -1, -1, 126, -1, -1, 129, 130, - 131, -1, -1, 134, -1, -1, -1, -1, 139, -1, - -1, 142, -1, -1, -1, 146, 3, 4, 5, 6, - 151, 8, 9, 10, 11, -1, 18, 19, 20, 21, - 22, 23, 24, 164, -1, -1, 167, 168, 169, -1, - -1, 172, 34, 174, 175, -1, -1, 178, -1, -1, - -1, -1, 16, 17, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, 51, -1, -1, -1, 55, -1, - 34, 58, 59, 60, 61, -1, -1, -1, -1, -1, - 67, -1, -1, -1, 71, 72, -1, -1, -1, -1, - -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, - 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, -1, -1, -1, -1, -1, -1, -1, -1, 116, - -1, 118, 119, -1, 121, -1, -1, -1, -1, 126, - -1, -1, 129, 130, 131, -1, -1, 134, -1, -1, - -1, -1, 139, -1, -1, 142, -1, -1, -1, 146, - 3, 4, 5, 6, 151, 8, 9, 10, -1, -1, - -1, -1, 15, -1, -1, 167, 168, 169, 170, 171, - -1, 173, 174, 175, -1, 172, -1, 174, 175, -1, - -1, 178, -1, 157, -1, -1, -1, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 51, 173, - 174, 175, 176, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 67, 10, 11, 12, -1, 72, - -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, - -1, -1, -1, -1, 87, -1, -1, -1, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 3, 4, 5, 6, -1, 8, - 9, 10, -1, -1, -1, -1, 119, -1, 121, -1, - -1, -1, -1, 126, 69, -1, -1, -1, 131, -1, - 75, 134, -1, -1, -1, -1, 139, 82, 83, -1, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, 51, -1, -1, -1, -1, -1, 34, -1, - -1, 164, -1, -1, 167, 168, 169, -1, 67, 172, - 115, 174, 175, 72, -1, 178, 121, 122, -1, 124, - -1, -1, 81, 82, -1, 130, -1, 132, 87, -1, - -1, -1, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 119, -1, 121, -1, -1, -1, -1, 126, -1, -1, - -1, -1, 131, -1, -1, 134, 3, 4, 5, 6, - 139, 8, 9, 10, -1, -1, -1, -1, 15, -1, - -1, -1, -1, 3, 4, 5, 6, -1, 8, 9, - 10, -1, -1, -1, -1, 15, -1, -1, -1, -1, - -1, -1, -1, 172, -1, 174, 175, -1, -1, 178, - -1, 48, -1, 50, 51, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 67, 51, -1, -1, -1, 72, -1, -1, -1, -1, - -1, -1, -1, -1, 81, 82, -1, 67, -1, -1, - -1, -1, 72, 18, 19, 20, 21, 22, 23, 24, - -1, 81, 82, -1, -1, -1, -1, -1, -1, 34, - -1, -1, 18, 19, 20, 21, 22, 23, 24, 116, - -1, -1, 119, -1, 121, -1, -1, -1, 34, 126, - -1, -1, -1, -1, 131, -1, 116, 134, -1, 119, - -1, 121, 139, -1, -1, 142, 126, -1, -1, -1, - -1, 131, -1, -1, 134, -1, -1, -1, -1, 139, - -1, -1, 142, -1, -1, -1, -1, 164, -1, -1, - 167, 168, -1, -1, -1, 172, -1, 174, -1, -1, - -1, 178, -1, -1, 164, -1, -1, 167, 168, 6, - -1, -1, 172, -1, 174, -1, -1, -1, 178, 16, - 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, 10, 11, 12, 34, -1, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, -1, -1, -1, -1, -1, -1, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, - 175, -1, -1, 70, -1, -1, 162, 163, 164, 10, - 11, 167, 168, 169, 170, 171, -1, 173, 174, 175, - -1, -1, -1, 69, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, -1, 82, 83, -1, -1, - -1, -1, -1, -1, 34, -1, -1, -1, -1, 116, - -1, 52, -1, -1, 55, 56, -1, 58, 59, 60, - 61, 62, -1, -1, -1, -1, -1, 68, -1, -1, - 71, -1, -1, -1, 75, 121, 122, -1, 124, -1, - -1, -1, 83, -1, 130, -1, 132, -1, -1, 90, - 157, -1, -1, 160, -1, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 107, 174, 175, 10, - 11, 178, -1, -1, -1, -1, -1, -1, -1, 120, - -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, - -1, -1, -1, -1, 135, -1, -1, -1, -1, -1, - -1, -1, 143, 144, 145, 146, -1, -1, 149, -1, - 151, 52, -1, -1, 55, 56, -1, 58, 59, 60, - 61, 62, -1, -1, -1, -1, -1, 68, -1, -1, - 71, 172, -1, -1, 75, 165, 166, 167, 168, 169, - 170, 171, 83, 173, 174, 175, -1, -1, -1, 90, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, 107, -1, 34, 16, - 17, 18, 19, 20, 21, 22, 23, 24, -1, 120, - -1, -1, -1, -1, -1, -1, -1, 34, 129, 130, - -1, -1, -1, 55, 135, -1, 58, 59, 60, 61, - -1, -1, 143, 144, 145, 146, -1, -1, 149, 71, - 151, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, -1, -1, -1, 90, 34, - -1, 172, 16, 17, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, -1, 107, -1, -1, -1, -1, - 34, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, -1, -1, 129, 130, 34, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, 146, -1, -1, -1, 34, 151, - -1, -1, -1, -1, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 176, -1, 174, -1, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, -1, 173, 174, 175, 176, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, - -1, -1, -1, -1, -1, -1, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, - 175, 176, -1, -1, -1, -1, -1, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, -1, 173, - 174, 175, 176, -1, -1, -1, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, - 175, 176, -1, -1, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 176, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, - -1, -1, -1, -1, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 176, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, 18, - 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 34, 18, 19, 20, 21, - 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, - 175, 176, -1, -1, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 176, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, - -1, -1, 157, -1, -1, -1, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, - 175, -1, -1, -1, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, - 6, -1, -1, 17, 163, 164, 165, 166, 167, 168, - 169, 170, 171, -1, 173, 174, 175, -1, -1, -1, - -1, 163, 164, -1, -1, 167, 168, 169, 170, 171, - -1, 173, 174, 175, 48, -1, 50, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 54, 63, - -1, 65, -1, -1, -1, -1, -1, 63, 64, 65, - 66, -1, -1, -1, -1, -1, -1, -1, 82, -1, - 76, 77, 78, 79, -1, 6, -1, -1, -1, -1, - -1, -1, -1, 89, -1, -1, -1, 164, -1, -1, - 167, 168, 169, 170, 171, -1, 173, 174, 175, -1, - 114, -1, -1, 117, 118, -1, -1, 121, 114, -1, - -1, 10, 11, 12, -1, -1, -1, -1, -1, 125, - -1, -1, -1, 54, 138, -1, 132, -1, -1, -1, - 136, 137, 63, 64, 65, 66, 150, -1, -1, -1, - -1, -1, 148, -1, 150, 76, 77, 78, 79, -1, - 164, -1, -1, -1, -1, -1, 55, -1, 89, 58, - 59, 60, 61, 62, 63, 10, 11, 12, -1, -1, - -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 114, 83, -1, -1, -1, -1, -1, - -1, 90, -1, -1, 125, -1, -1, -1, -1, -1, - -1, 132, -1, -1, -1, -1, 137, -1, 107, -1, - 55, -1, -1, 58, 59, 60, 61, 148, -1, 150, - -1, -1, -1, 11, 12, -1, 71, -1, -1, -1, - 129, 130, -1, -1, -1, -1, -1, -1, 83, -1, - -1, -1, -1, -1, 143, 90, -1, 146, -1, -1, - 149, 150, 151, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 107, -1, 52, -1, -1, 55, 56, -1, - 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, - 68, -1, -1, 71, 129, 130, -1, 75, 11, 12, - -1, -1, -1, -1, -1, 83, -1, -1, -1, -1, - -1, 146, 90, -1, 149, -1, 151, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 107, - -1, 11, -1, -1, -1, -1, -1, -1, -1, 52, - -1, -1, 55, 56, -1, 58, 59, 60, 61, 62, - -1, 129, 130, -1, -1, 68, -1, 135, 71, -1, - -1, -1, 75, -1, -1, 143, 144, 145, 146, -1, - 83, 149, 52, 151, -1, 55, 56, 90, 58, 59, - 60, 61, 62, 63, -1, -1, -1, -1, 68, -1, - -1, 71, -1, -1, 107, 75, 11, -1, -1, -1, - -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, - 90, -1, -1, -1, -1, -1, 129, 130, -1, -1, - -1, -1, 135, -1, -1, -1, -1, 107, -1, 11, - 143, 144, 145, 146, -1, -1, 149, 52, 151, -1, - 55, 56, -1, 58, 59, 60, 61, 62, 63, 129, - 130, -1, -1, 68, -1, 135, 71, -1, -1, -1, - 75, -1, -1, 143, 144, 145, 146, -1, 83, 149, - 52, 151, -1, 55, 56, 90, 58, 59, 60, 61, - 62, -1, -1, -1, -1, -1, 68, -1, -1, 71, - -1, -1, 107, 75, 11, -1, -1, -1, -1, -1, - -1, 83, -1, -1, -1, -1, -1, -1, 90, -1, - -1, 10, 11, 12, 129, 130, -1, -1, -1, -1, - 135, -1, -1, -1, -1, 107, -1, -1, 143, 144, - 145, 146, -1, -1, 149, 52, 151, -1, 55, 56, - -1, 58, 59, 60, 61, 62, -1, 129, 130, -1, - -1, 68, -1, 135, 71, -1, -1, -1, 75, -1, - -1, 143, 144, 145, 146, -1, 83, 149, -1, 151, - 69, -1, -1, 90, -1, -1, -1, -1, 10, 11, - 12, -1, -1, 82, 83, -1, -1, -1, -1, -1, - 107, -1, -1, 10, 11, 12, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, - 12, -1, 129, 130, -1, -1, -1, -1, 135, -1, - -1, -1, 121, 122, 123, 124, 143, 144, 145, 146, - -1, 130, 149, 132, 151, -1, -1, 69, -1, -1, - -1, -1, -1, -1, 143, -1, -1, -1, -1, 148, - 82, 83, 69, -1, -1, -1, -1, -1, 55, -1, - -1, 58, 59, 60, 61, 82, 83, 69, -1, -1, - 10, 11, 12, -1, -1, 15, -1, -1, -1, -1, - 82, 83, 55, -1, -1, 58, 59, 60, 61, 121, - 122, -1, 124, 90, -1, -1, -1, -1, 130, -1, - 132, -1, -1, -1, 121, 122, -1, 124, -1, -1, - 107, 143, -1, 130, -1, 132, 148, 90, -1, 121, - 122, -1, 124, -1, -1, -1, 143, -1, 130, 69, - 132, 148, 129, 130, 107, -1, -1, -1, -1, -1, - -1, 143, 82, 83, -1, -1, 148, -1, -1, 146, - -1, -1, -1, -1, 151, -1, 129, 130, 55, -1, - -1, 58, 59, 60, 61, -1, -1, -1, -1, -1, - -1, -1, -1, 146, -1, -1, -1, 174, 151, -1, - -1, 121, 122, -1, 124, -1, -1, -1, -1, -1, - 130, -1, 132, 90, -1, 54, -1, -1, -1, -1, - -1, 174, -1, -1, 63, 64, 65, 66, -1, -1, - 107, -1, -1, -1, -1, -1, -1, 76, 77, 78, - 79, -1, -1, -1, -1, 84, -1, -1, -1, -1, - 89, -1, 129, 130, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 146, - -1, -1, -1, -1, 151, 114, -1, -1, -1, 53, - 54, -1, -1, -1, -1, -1, 125, -1, -1, 63, - 64, 65, 66, 132, -1, -1, -1, 174, 137, -1, - 74, -1, 76, 77, 78, 79, 80, -1, 147, 148, - 84, 150, -1, -1, -1, 89, -1, -1, -1, -1, - 54, -1, -1, -1, -1, -1, 165, -1, -1, 63, - 64, 65, 66, -1, 108, 109, 110, 111, 112, 113, - 114, 115, 76, 77, 78, 79, -1, -1, 122, 123, - 124, 125, -1, -1, -1, 89, -1, -1, 132, 133, - 54, -1, 136, 137, -1, -1, -1, 141, -1, 63, - 64, 65, 66, 147, 148, -1, 150, 54, -1, -1, - 114, 115, 76, 77, 78, 79, 63, 64, 65, 66, - 84, 125, -1, -1, -1, 89, -1, -1, 132, 76, - 77, 78, 79, 137, -1, -1, -1, -1, -1, -1, - -1, -1, 89, -1, 148, -1, 150, -1, -1, -1, - 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 125, -1, -1, -1, -1, -1, 114, 132, -1, - -1, -1, 136, 137, -1, -1, -1, -1, 125, -1, - -1, -1, -1, 147, 148, 132, 150, -1, -1, -1, - 137, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 148, -1, 150 -}; - -/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of - state STATE-NUM. */ -static const yytype_int16 yystos[] = -{ - 0, 153, 154, 155, 181, 182, 292, 3, 4, 5, - 6, 8, 9, 10, 11, 51, 55, 58, 59, 60, - 61, 67, 71, 72, 81, 82, 83, 87, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 116, 118, 119, 121, - 126, 129, 130, 131, 134, 139, 142, 146, 151, 164, - 167, 168, 169, 172, 174, 175, 178, 282, 283, 291, - 11, 12, 52, 55, 56, 58, 59, 60, 61, 62, - 63, 68, 71, 75, 83, 90, 107, 129, 130, 135, - 143, 144, 145, 146, 149, 151, 244, 245, 249, 250, - 252, 258, 260, 264, 265, 270, 271, 272, 273, 0, - 48, 50, 192, 292, 156, 174, 174, 174, 174, 174, - 174, 174, 165, 174, 165, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 11, 52, 56, 68, 143, - 144, 247, 264, 265, 270, 282, 165, 174, 174, 15, - 174, 282, 165, 174, 174, 174, 282, 282, 282, 282, - 282, 11, 55, 58, 59, 60, 61, 71, 83, 90, - 107, 129, 130, 146, 151, 249, 280, 282, 10, 11, - 12, 69, 82, 83, 121, 122, 124, 130, 132, 160, - 164, 169, 286, 287, 289, 292, 282, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 34, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 173, 174, - 175, 6, 8, 244, 245, 174, 62, 135, 71, 107, - 271, 271, 271, 289, 174, 271, 13, 15, 17, 63, - 127, 150, 164, 169, 174, 242, 243, 292, 243, 259, - 192, 192, 147, 193, 194, 289, 174, 158, 183, 279, - 280, 292, 279, 249, 279, 279, 279, 279, 279, 249, - 279, 249, 279, 249, 279, 249, 249, 249, 249, 249, - 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, - 249, 279, 174, 289, 174, 174, 192, 192, 176, 249, - 279, 279, 174, 249, 249, 249, 282, 279, 279, 176, - 157, 176, 289, 289, 157, 179, 160, 232, 292, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 289, 176, 280, 282, 243, 243, 52, 282, 249, 169, - 289, 192, 242, 243, 242, 243, 242, 243, 192, 192, - 15, 17, 164, 169, 192, 227, 228, 237, 292, 175, - 156, 10, 11, 12, 121, 159, 290, 10, 11, 12, - 121, 156, 289, 290, 289, 49, 157, 174, 11, 52, - 56, 68, 143, 144, 246, 250, 252, 258, 264, 265, - 270, 282, 53, 54, 63, 64, 65, 66, 74, 76, - 77, 78, 79, 80, 84, 89, 108, 109, 110, 111, - 112, 113, 114, 115, 122, 123, 124, 125, 132, 133, - 136, 137, 141, 147, 148, 150, 186, 188, 189, 191, - 195, 215, 266, 269, 292, 177, 176, 176, 176, 176, - 176, 176, 176, 166, 176, 166, 176, 176, 176, 176, - 157, 176, 157, 176, 157, 176, 176, 176, 176, 176, - 176, 176, 176, 176, 176, 176, 176, 282, 249, 279, - 289, 289, 166, 176, 176, 289, 176, 166, 176, 176, - 176, 176, 282, 282, 15, 164, 287, 174, 212, 292, - 282, 159, 176, 179, 176, 176, 176, 192, 192, 13, - 15, 17, 63, 127, 150, 164, 169, 242, 292, 242, - 242, 192, 192, 192, 77, 89, 191, 176, 15, 157, - 278, 282, 292, 262, 263, 292, 11, 261, 271, 159, - 251, 253, 159, 192, 193, 3, 4, 5, 9, 10, - 15, 51, 67, 72, 81, 82, 116, 119, 121, 126, - 131, 134, 139, 142, 164, 167, 168, 172, 174, 178, - 229, 230, 237, 238, 284, 285, 291, 292, 174, 289, - 174, 176, 192, 192, 176, 191, 191, 191, 191, 191, - 191, 6, 191, 215, 191, 282, 159, 190, 115, 191, - 174, 174, 174, 174, 174, 174, 191, 156, 192, 159, - 159, 159, 191, 191, 174, 189, 191, 195, 216, 191, - 191, 199, 75, 115, 289, 191, 191, 10, 11, 120, - 156, 172, 202, 206, 246, 248, 174, 174, 249, 249, - 249, 176, 176, 176, 174, 176, 174, 232, 227, 17, - 63, 65, 82, 114, 117, 118, 121, 138, 150, 164, - 192, 282, 242, 169, 289, 192, 242, 242, 242, 192, - 192, 175, 242, 242, 242, 244, 245, 212, 15, 237, - 179, 289, 177, 261, 182, 82, 254, 292, 193, 174, - 165, 165, 247, 165, 15, 174, 284, 165, 174, 282, - 282, 282, 282, 249, 280, 282, 176, 15, 157, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 34, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 173, 174, 175, 52, 282, 249, 192, 289, 290, 289, - 192, 191, 176, 188, 156, 289, 289, 289, 289, 289, - 289, 289, 182, 289, 282, 165, 10, 11, 206, 246, - 248, 289, 289, 158, 192, 174, 174, 63, 244, 187, - 289, 197, 156, 158, 160, 234, 158, 196, 280, 280, - 176, 176, 176, 280, 280, 176, 282, 174, 34, 225, - 292, 192, 192, 242, 242, 242, 278, 176, 176, 176, - 13, 17, 63, 127, 150, 164, 169, 174, 240, 290, - 292, 13, 15, 17, 63, 127, 150, 164, 169, 174, - 241, 192, 192, 192, 177, 159, 255, 256, 292, 49, - 249, 249, 249, 174, 249, 174, 249, 249, 249, 282, - 176, 176, 15, 238, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 289, 176, 280, 282, 176, - 176, 176, 159, 191, 182, 156, 157, 157, 157, 157, - 157, 157, 177, 156, 157, 176, 10, 11, 12, 62, - 63, 143, 150, 217, 218, 219, 220, 221, 270, 292, - 174, 234, 200, 158, 158, 160, 203, 10, 13, 169, - 205, 244, 13, 17, 63, 127, 150, 164, 169, 239, - 290, 292, 182, 174, 156, 158, 159, 160, 233, 274, - 275, 69, 70, 156, 282, 13, 17, 63, 120, 150, - 164, 169, 174, 198, 222, 224, 290, 176, 176, 176, - 176, 212, 176, 176, 289, 63, 247, 156, 242, 179, - 174, 174, 174, 169, 192, 240, 240, 240, 192, 192, - 240, 175, 232, 192, 169, 289, 192, 241, 241, 241, - 192, 192, 241, 175, 232, 225, 157, 160, 122, 123, - 124, 143, 148, 257, 288, 289, 156, 157, 192, 176, - 166, 166, 279, 166, 289, 176, 166, 176, 176, 282, - 159, 176, 179, 261, 177, 268, 10, 10, 10, 10, - 10, 10, 267, 291, 158, 221, 221, 166, 157, 15, - 289, 13, 17, 63, 127, 150, 164, 169, 174, 240, - 241, 201, 224, 249, 227, 176, 169, 222, 227, 239, - 169, 192, 239, 239, 239, 192, 192, 174, 175, 192, - 177, 207, 274, 184, 185, 289, 69, 70, 177, 276, - 292, 158, 158, 156, 235, 236, 282, 292, 158, 169, - 192, 222, 6, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 34, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 70, 116, 157, 160, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, - 174, 175, 178, 213, 222, 192, 192, 222, 159, 174, - 175, 225, 160, 232, 234, 192, 192, 15, 176, 247, - 243, 274, 192, 227, 227, 227, 192, 240, 240, 240, - 176, 278, 192, 192, 241, 241, 241, 176, 278, 282, - 148, 288, 148, 288, 148, 288, 289, 122, 123, 124, - 15, 182, 257, 174, 174, 176, 174, 176, 174, 282, - 182, 157, 157, 176, 157, 226, 292, 157, 157, 157, - 182, 176, 240, 241, 240, 241, 189, 195, 214, 215, - 220, 289, 160, 169, 192, 192, 192, 160, 231, 292, - 232, 234, 158, 176, 174, 222, 176, 176, 174, 192, - 239, 239, 239, 210, 278, 227, 177, 156, 157, 156, - 174, 158, 158, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 75, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 88, 89, 90, 107, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 178, - 179, 277, 235, 177, 157, 192, 222, 10, 176, 179, - 192, 222, 222, 176, 282, 223, 278, 282, 157, 225, - 176, 243, 177, 176, 176, 176, 240, 174, 179, 241, - 174, 179, 157, 288, 288, 288, 288, 288, 288, 177, - 280, 280, 280, 280, 177, 10, 10, 158, 10, 176, - 10, 10, 10, 177, 158, 231, 231, 249, 192, 51, - 67, 72, 126, 131, 134, 164, 167, 168, 169, 172, - 174, 178, 281, 283, 157, 212, 204, 176, 174, 212, - 211, 239, 227, 179, 176, 274, 185, 279, 279, 276, - 177, 156, 282, 222, 192, 229, 179, 198, 156, 212, - 212, 212, 227, 192, 227, 192, 176, 176, 176, 176, - 176, 157, 176, 157, 158, 157, 176, 176, 157, 176, - 174, 165, 165, 165, 15, 174, 281, 165, 281, 281, - 281, 281, 281, 249, 280, 281, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 34, 161, 162, 163, 164, - 167, 168, 169, 170, 171, 173, 174, 175, 201, 192, - 227, 174, 208, 192, 227, 176, 192, 212, 177, 177, - 176, 177, 235, 176, 192, 274, 192, 192, 192, 176, - 176, 158, 10, 158, 10, 10, 158, 158, 10, 158, - 249, 249, 249, 249, 174, 249, 249, 176, 176, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 289, 176, - 280, 282, 176, 209, 227, 176, 212, 192, 15, 177, - 212, 177, 225, 225, 225, 212, 212, 157, 226, 176, - 157, 157, 176, 176, 166, 166, 166, 289, 176, 166, - 281, 159, 176, 179, 212, 227, 176, 212, 192, 192, - 192, 10, 176, 158, 10, 10, 158, 174, 174, 174, - 176, 174, 281, 192, 176, 212, 158, 176, 157, 176, - 280, 280, 280, 280, 212, 192, 158, 10, 158, 176, - 176, 176, 176, 192, 225, 176, 225, 158 -}; - -/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ -static const yytype_int16 yyr1[] = -{ - 0, 180, 181, 181, 181, 182, 182, 183, 182, 184, - 184, 185, 185, 185, 187, 186, 188, 188, 188, 188, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 190, 189, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 192, 192, 192, 192, 192, 193, 193, - 194, 194, 196, 195, 195, 197, 195, 195, 195, 198, - 198, 200, 199, 199, 201, 201, 203, 202, 204, 202, - 205, 202, 207, 206, 208, 206, 209, 206, 210, 206, - 211, 206, 206, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 214, 214, 214, - 215, 216, 215, 215, 215, 217, 217, 218, 218, 219, - 219, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 221, 221, 221, 221, 222, 222, 222, 222, - 222, 222, 222, 222, 222, 222, 222, 223, 222, 224, - 224, 225, 225, 225, 226, 226, 227, 227, 227, 227, - 227, 228, 228, 229, 229, 229, 229, 229, 230, 230, - 231, 231, 232, 232, 233, 233, 233, 233, 233, 234, - 234, 234, 234, 234, 234, 235, 235, 235, 236, 236, - 236, 236, 237, 237, 238, 238, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, - 240, 240, 240, 240, 240, 240, 240, 240, 241, 241, - 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, - 242, 243, 243, 243, 243, 243, 243, 243, 243, 243, - 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, - 244, 244, 244, 244, 244, 244, 244, 244, 244, 245, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, - 247, 247, 247, 248, 248, 249, 249, 249, 249, 251, - 250, 253, 252, 254, 254, 255, 255, 256, 256, 257, - 257, 257, 257, 257, 257, 257, 257, 257, 257, 259, - 258, 260, 260, 260, 260, 261, 261, 262, 262, 262, - 263, 263, 263, 264, 264, 264, 265, 265, 265, 267, - 266, 268, 266, 266, 266, 269, 269, 269, 269, 270, - 270, 270, 271, 271, 271, 271, 271, 271, 271, 271, - 271, 271, 271, 271, 271, 271, 271, 272, 272, 272, - 273, 275, 274, 276, 276, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, - 277, 277, 277, 278, 278, 279, 279, 280, 280, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 283, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 285, 285, 285, - 285, 285, 285, 285, 285, 285, 285, 285, 286, 286, - 286, 286, 286, 287, 287, 287, 287, 288, 288, 288, - 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, - 289, 290, 290, 290, 290, 291, 291, 291, 291, 292 -}; - -/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ -static const yytype_int8 yyr2[] = -{ - 0, 2, 2, 2, 2, 1, 3, 0, 4, 1, - 3, 4, 5, 4, 0, 5, 1, 1, 1, 1, - 1, 2, 1, 1, 2, 2, 2, 2, 8, 11, - 9, 11, 13, 15, 7, 9, 12, 9, 9, 13, - 9, 7, 5, 0, 3, 1, 2, 2, 3, 2, - 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 4, 7, 5, 5, 1, 3, - 1, 4, 0, 4, 3, 0, 4, 3, 1, 2, - 4, 0, 4, 3, 2, 4, 0, 7, 0, 10, - 0, 7, 0, 8, 0, 12, 0, 13, 0, 8, - 0, 9, 1, 1, 2, 2, 2, 4, 2, 2, - 2, 2, 2, 2, 4, 5, 6, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, - 2, 0, 6, 2, 2, 1, 1, 1, 3, 1, - 1, 1, 2, 4, 2, 3, 3, 4, 2, 3, - 4, 3, 1, 1, 1, 1, 2, 3, 4, 2, - 2, 3, 3, 3, 4, 5, 3, 0, 7, 2, - 3, 1, 3, 4, 1, 2, 1, 1, 1, 3, - 2, 1, 3, 1, 1, 1, 3, 2, 1, 3, - 1, 2, 1, 2, 1, 3, 5, 3, 3, 1, - 3, 3, 3, 3, 4, 1, 1, 2, 1, 3, - 3, 5, 5, 5, 1, 1, 1, 2, 2, 2, - 2, 3, 3, 3, 4, 5, 1, 2, 2, 2, - 2, 3, 3, 3, 4, 5, 8, 3, 1, 3, - 2, 2, 2, 3, 3, 3, 4, 5, 8, 3, - 1, 1, 3, 2, 2, 2, 3, 3, 3, 4, - 5, 1, 1, 3, 2, 2, 2, 3, 3, 3, - 4, 5, 6, 11, 11, 11, 1, 1, 2, 1, - 1, 1, 3, 5, 4, 4, 4, 1, 1, 1, - 1, 1, 2, 1, 1, 1, 3, 5, 3, 4, - 4, 4, 1, 1, 1, 1, 2, 3, 3, 4, - 4, 1, 1, 1, 1, 2, 3, 2, 3, 0, - 6, 0, 9, 1, 1, 1, 1, 2, 3, 1, - 2, 2, 2, 3, 3, 3, 3, 3, 3, 0, - 5, 4, 2, 5, 3, 1, 1, 1, 4, 6, - 1, 3, 5, 1, 2, 2, 1, 1, 1, 0, - 7, 0, 7, 4, 5, 3, 6, 4, 4, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, - 1, 0, 2, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, - 4, 7, 7, 7, 7, 4, 2, 5, 4, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 5, 4, 4, 3, 3, 3, 3, 1, - 4, 7, 7, 7, 7, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 2, 5, 4, 2, 5, 4, 4, 2, 2, - 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 9, 12, 4, 4, 6, 4, 4, 6, - 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 1, 4, 7, 7, 7, 7, 4, 2, - 5, 4, 2, 5, 4, 4, 2, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 4, 4, 3, 3, 3, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 2, 3, 1, 2, 1, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 0 -}; - - -enum { YYENOMEM = -2 }; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab -#define YYNOMEM goto yyexhaustedlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ - do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ - while (0) - -/* Backward compatibility with an undocumented macro. - Use YYerror or YYUNDEF. */ -#define YYERRCODE YYUNDEF - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (0) -#endif - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - - -/* YYLOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -# ifndef YYLOCATION_PRINT - -# if defined YY_LOCATION_PRINT - - /* Temporary convenience wrapper in case some people defined the - undocumented and private YY_LOCATION_PRINT macros. */ -# define YYLOCATION_PRINT(File, Loc) YY_LOCATION_PRINT(File, *(Loc)) - -# elif defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - -/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ - -YY_ATTRIBUTE_UNUSED -static int -yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) -{ - int res = 0; - int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; - if (0 <= yylocp->first_line) - { - res += YYFPRINTF (yyo, "%d", yylocp->first_line); - if (0 <= yylocp->first_column) - res += YYFPRINTF (yyo, ".%d", yylocp->first_column); - } - if (0 <= yylocp->last_line) - { - if (yylocp->first_line < yylocp->last_line) - { - res += YYFPRINTF (yyo, "-%d", yylocp->last_line); - if (0 <= end_col) - res += YYFPRINTF (yyo, ".%d", end_col); - } - else if (0 <= end_col && yylocp->first_column < end_col) - res += YYFPRINTF (yyo, "-%d", end_col); - } - return res; -} - -# define YYLOCATION_PRINT yy_location_print_ - - /* Temporary convenience wrapper in case some people defined the - undocumented and private YY_LOCATION_PRINT macros. */ -# define YY_LOCATION_PRINT(File, Loc) YYLOCATION_PRINT(File, &(Loc)) - -# else - -# define YYLOCATION_PRINT(File, Loc) ((void) 0) - /* Temporary convenience wrapper in case some people defined the - undocumented and private YY_LOCATION_PRINT macros. */ -# define YY_LOCATION_PRINT YYLOCATION_PRINT - -# endif -# endif /* !defined YYLOCATION_PRINT */ - - -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Kind, Value, Location); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*-----------------------------------. -| Print this symbol's value on YYO. | -`-----------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) -{ - FILE *yyoutput = yyo; - YY_USE (yyoutput); - YY_USE (yylocationp); - if (!yyvaluep) - return; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/*---------------------------. -| Print this symbol on YYO. | -`---------------------------*/ - -static void -yy_symbol_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) -{ - YYFPRINTF (yyo, "%s %s (", - yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - - YYLOCATION_PRINT (yyo, yylocationp); - YYFPRINTF (yyo, ": "); - yy_symbol_value_print (yyo, yykind, yyvaluep, yylocationp); - YYFPRINTF (yyo, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, - int yyrule) -{ - int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), - &yyvsp[(yyi + 1) - (yynrhs)], - &(yylsp[(yyi + 1) - (yynrhs)])); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, yylsp, Rule); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) ((void) 0) -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - - - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, - yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) -{ - YY_USE (yyvaluep); - YY_USE (yylocationp); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (void) -{ -/* Lookahead token kind. */ -int yychar; - - -/* The semantic value of the lookahead symbol. */ -/* Default value used for initialization, for pacifying older GCCs - or non-GCC compilers. */ -YY_INITIAL_VALUE (static YYSTYPE yyval_default;) -YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - -/* Location data for the lookahead symbol. */ -static YYLTYPE yyloc_default -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - = { 1, 1, 1, 1 } -# endif -; -YYLTYPE yylloc = yyloc_default; - - /* Number of syntax errors so far. */ - int yynerrs = 0; - - yy_state_fast_t yystate = 0; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus = 0; - - /* Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* Their size. */ - YYPTRDIFF_T yystacksize = YYINITDEPTH; - - /* The state stack: array, bottom, top. */ - yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss = yyssa; - yy_state_t *yyssp = yyss; - - /* The semantic value stack: array, bottom, top. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp = yyvs; - - /* The location stack: array, bottom, top. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp = yyls; - - int yyn; - /* The return value of yyparse. */ - int yyresult; - /* Lookahead symbol kind. */ - yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - YYLTYPE yyloc; - - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[3]; - - - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yychar = YYEMPTY; /* Cause a token to be read. */ - - yylsp[0] = yylloc; - goto yysetstate; - - -/*------------------------------------------------------------. -| yynewstate -- push a new state, which is found in yystate. | -`------------------------------------------------------------*/ -yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - -/*--------------------------------------------------------------------. -| yysetstate -- set current state (the top of the stack) to yystate. | -`--------------------------------------------------------------------*/ -yysetstate: - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - YY_ASSERT (0 <= yystate && yystate < YYNSTATES); - YY_IGNORE_USELESS_CAST_BEGIN - *yyssp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - YY_STACK_PRINT (yyss, yyssp); - - if (yyss + yystacksize - 1 <= yyssp) -#if !defined yyoverflow && !defined YYSTACK_RELOCATE - YYNOMEM; -#else - { - /* Get the current used size of the three stacks, in elements. */ - YYPTRDIFF_T yysize = yyssp - yyss + 1; - -# if defined yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - yy_state_t *yyss1 = yyss; - YYSTYPE *yyvs1 = yyvs; - YYLTYPE *yyls1 = yyls; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * YYSIZEOF (*yyssp), - &yyvs1, yysize * YYSIZEOF (*yyvsp), - &yyls1, yysize * YYSIZEOF (*yylsp), - &yystacksize); - yyss = yyss1; - yyvs = yyvs1; - yyls = yyls1; - } -# else /* defined YYSTACK_RELOCATE */ - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - YYNOMEM; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yy_state_t *yyss1 = yyss; - union yyalloc *yyptr = - YY_CAST (union yyalloc *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); - if (! yyptr) - YYNOMEM; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); - YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - yylsp = yyls + yysize - 1; - - YY_IGNORE_USELESS_CAST_BEGIN - YYDPRINTF ((stderr, "Stack size increased to %ld\n", - YY_CAST (long, yystacksize))); - YY_IGNORE_USELESS_CAST_END - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } -#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token\n")); - yychar = yylex (&yylval, &yylloc); - } - - if (yychar <= YYEOF) - { - yychar = YYEOF; - yytoken = YYSYMBOL_YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else if (yychar == YYerror) - { - /* The scanner already issued an error message, process directly - to error recovery. But do not keep the error token as - lookahead, it is too special and may lead us to an endless - loop in error recovery. */ - yychar = YYUNDEF; - yytoken = YYSYMBOL_YYerror; - yyerror_range[1] = yylloc; - goto yyerrlab1; - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - *++yylsp = yylloc; - - /* Discard the shifted token. */ - yychar = YYEMPTY; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - /* Default location. */ - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); - yyerror_range[1] = yyloc; - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 3: /* grammar: START_CONST_EXPR const_expr */ -#line 468 "dtool/src/cppparser/cppBison.yxx" -{ - current_expr = (yyvsp[0].u.expr); -} -#line 3882 "built/tmp/cppBison.yxx.c" - break; - - case 4: /* grammar: START_TYPE full_type */ -#line 472 "dtool/src/cppparser/cppBison.yxx" -{ - current_type = (yyvsp[0].u.type); -} -#line 3890 "built/tmp/cppBison.yxx.c" - break; - - case 6: /* cpp: cpp optional_attributes ';' */ -#line 480 "dtool/src/cppparser/cppBison.yxx" -{ - if (!(yyvsp[-1].attr_list).is_empty()) { - current_scope->add_declaration(new CPPDeclaration((yylsp[-1]).file, (yyvsp[-1].attr_list)), global_scope, current_lexer, (yylsp[-1])); - } -} -#line 3900 "built/tmp/cppBison.yxx.c" - break; - - case 7: /* $@1: %empty */ -#line 486 "dtool/src/cppparser/cppBison.yxx" -{ - current_attributes = (yyvsp[0].attr_list); -} -#line 3908 "built/tmp/cppBison.yxx.c" - break; - - case 8: /* cpp: cpp optional_attributes $@1 declaration */ -#line 490 "dtool/src/cppparser/cppBison.yxx" -{ - current_attributes = CPPAttributeList(); -} -#line 3916 "built/tmp/cppBison.yxx.c" - break; - - case 11: /* constructor_init: name '(' optional_const_expr_comma ')' */ -#line 502 "dtool/src/cppparser/cppBison.yxx" -{ - delete (yyvsp[-1].u.expr); -} -#line 3924 "built/tmp/cppBison.yxx.c" - break; - - case 12: /* constructor_init: name '(' optional_const_expr_comma ')' ELLIPSIS */ -#line 506 "dtool/src/cppparser/cppBison.yxx" -{ - delete (yyvsp[-2].u.expr); -} -#line 3932 "built/tmp/cppBison.yxx.c" - break; - - case 13: /* constructor_init: name '{' optional_const_expr_comma '}' */ -#line 510 "dtool/src/cppparser/cppBison.yxx" -{ - delete (yyvsp[-1].u.expr); -} -#line 3940 "built/tmp/cppBison.yxx.c" - break; - - case 14: /* $@2: %empty */ -#line 522 "dtool/src/cppparser/cppBison.yxx" -{ - push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | - ((yyvsp[-1].u.integer) & CPPInstance::SC_c_binding)); -} -#line 3949 "built/tmp/cppBison.yxx.c" - break; - - case 15: /* extern_c: storage_class '{' $@2 cpp '}' */ -#line 527 "dtool/src/cppparser/cppBison.yxx" -{ - pop_storage_class(); -} -#line 3957 "built/tmp/cppBison.yxx.c" - break; - - case 22: /* declaration: KW_BEGIN_PUBLISH */ -#line 540 "dtool/src/cppparser/cppBison.yxx" -{ - if (publish_nest_level != 0) { - yyerror("Unclosed __begin_publish", publish_loc); - publish_nest_level = 0; - current_scope->set_current_vis(V_public); - } - - publish_previous = current_scope->get_current_vis(); - publish_loc = (yylsp[0]); - publish_nest_level++; - current_scope->set_current_vis(V_published); -} -#line 3974 "built/tmp/cppBison.yxx.c" - break; - - case 23: /* declaration: KW_END_PUBLISH */ -#line 553 "dtool/src/cppparser/cppBison.yxx" -{ - if (publish_nest_level != 1) { - yyerror("Unmatched __end_publish", (yylsp[0])); - } else { - current_scope->set_current_vis(publish_previous); - } - publish_nest_level = 0; -} -#line 3987 "built/tmp/cppBison.yxx.c" - break; - - case 24: /* declaration: KW_PUBLISHED ':' */ -#line 562 "dtool/src/cppparser/cppBison.yxx" -{ - current_scope->set_current_vis(V_published); -} -#line 3995 "built/tmp/cppBison.yxx.c" - break; - - case 25: /* declaration: KW_PUBLIC ':' */ -#line 566 "dtool/src/cppparser/cppBison.yxx" -{ - if (publish_nest_level > 0) { - current_scope->set_current_vis(V_published); - } else { - current_scope->set_current_vis(V_public); - } -} -#line 4007 "built/tmp/cppBison.yxx.c" - break; - - case 26: /* declaration: KW_PROTECTED ':' */ -#line 574 "dtool/src/cppparser/cppBison.yxx" -{ - current_scope->set_current_vis(V_protected); -} -#line 4015 "built/tmp/cppBison.yxx.c" - break; - - case 27: /* declaration: KW_PRIVATE ':' */ -#line 578 "dtool/src/cppparser/cppBison.yxx" -{ - current_scope->set_current_vis(V_private); -} -#line 4023 "built/tmp/cppBison.yxx.c" - break; - - case 28: /* declaration: KW_MAKE_PROPERTY '(' name ',' IDENTIFIER maybe_comma_identifier ')' ';' */ -#line 582 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-3].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-3].u.identifier)->get_fully_scoped_name(), (yylsp[-3])); - } else { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-5].u.identifier), CPPMakeProperty::T_normal, current_scope, (yylsp[-7]).file); - make_property->_get_function = getter->as_function_group(); - - if ((yyvsp[-2].u.identifier) != nullptr) { - CPPDeclaration *setter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_set_function = setter->as_function_group(); - } - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-7])); - } -} -#line 4048 "built/tmp/cppBison.yxx.c" - break; - - case 29: /* declaration: KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 603 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - - } else { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-8].u.identifier), CPPMakeProperty::T_normal, current_scope, (yylsp[-10]).file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *setter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *deleter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_del_function = deleter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-10])); - } -} -#line 4079 "built/tmp/cppBison.yxx.c" - break; - - case 30: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 630 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - length_getter = nullptr; - } - - CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-6].u.identifier), CPPMakeProperty::T_sequence, current_scope, (yylsp[-8]).file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); - } -} -#line 4104 "built/tmp/cppBison.yxx.c" - break; - - case 31: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 651 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *length_getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - length_getter = nullptr; - } - - CPPDeclaration *getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-8].u.identifier), CPPMakeProperty::T_sequence, current_scope, (yylsp[-10]).file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - - CPPDeclaration *setter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_set_function = setter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-10])); - } -} -#line 4137 "built/tmp/cppBison.yxx.c" - break; - - case 32: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 680 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *length_getter = (yyvsp[-8].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[-8].u.identifier)->get_fully_scoped_name(), (yylsp[-8])); - length_getter = nullptr; - } - - CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-10].u.identifier), CPPMakeProperty::T_sequence, current_scope, (yylsp[-12]).file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - - CPPDeclaration *setter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *deleter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_del_function = deleter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-12])); - } -} -#line 4177 "built/tmp/cppBison.yxx.c" - break; - - case 33: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 716 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *length_getter = (yyvsp[-10].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[-10].u.identifier)->get_fully_scoped_name(), (yylsp[-10])); - length_getter = nullptr; - } - - CPPDeclaration *getter = (yyvsp[-8].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-8].u.identifier)->get_fully_scoped_name(), (yylsp[-8])); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-12].u.identifier), CPPMakeProperty::T_sequence, current_scope, (yylsp[-14]).file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - - CPPDeclaration *setter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *deleter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - } else { - make_property->_del_function = deleter->as_function_group(); - } - - CPPDeclaration *inserter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (inserter == nullptr || inserter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid append method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_insert_function = inserter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-14])); - } -} -#line 4224 "built/tmp/cppBison.yxx.c" - break; - - case 34: /* declaration: KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ')' ';' */ -#line 759 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid item getter method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - - } else { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-4].u.identifier), CPPMakeProperty::T_mapping, current_scope, (yylsp[-6]).file); - make_property->_get_function = getter->as_function_group(); - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-6])); - } -} -#line 4240 "built/tmp/cppBison.yxx.c" - break; - - case 35: /* declaration: KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 771 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - - } else { - CPPMakeProperty *make_property; - make_property = new CPPMakeProperty((yyvsp[-6].u.identifier), CPPMakeProperty::T_mapping, current_scope, (yylsp[-8]).file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); - } -} -#line 4265 "built/tmp/cppBison.yxx.c" - break; - - case 36: /* declaration: KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER maybe_comma_identifier ')' ';' */ -#line 792 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-5].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-5].u.identifier)->get_fully_scoped_name(), (yylsp[-5])); - - } else { - CPPMakeProperty *make_property = new CPPMakeProperty((yyvsp[-9].u.identifier), CPPMakeProperty::T_mapping, current_scope, (yylsp[-11]).file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = (yyvsp[-7].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + (yyvsp[-7].u.identifier)->get_fully_scoped_name(), (yylsp[-7])); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - CPPDeclaration *setter = (yyvsp[-3].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + (yyvsp[-3].u.identifier)->get_fully_scoped_name(), (yylsp[-3])); - } else { - make_property->_set_function = setter->as_function_group(); - } - - if ((yyvsp[-2].u.identifier) != nullptr) { - CPPDeclaration *deleter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_del_function = deleter->as_function_group(); - } - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-11])); - } -} -#line 4305 "built/tmp/cppBison.yxx.c" - break; - - case 37: /* declaration: KW_MAKE_MAP_KEYS_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 828 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - length_getter = nullptr; - } - - CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = nullptr; - for (size_t i = 0; i < current_scope->_declarations.size(); ++i) { - make_property = current_scope->_declarations[i]->as_make_property(); - if (make_property != nullptr) { - if (make_property->get_fully_scoped_name() == (yyvsp[-6].u.identifier)->get_fully_scoped_name()) { - break; - } else { - make_property = nullptr; - } - } - } - if (make_property != nullptr) { - make_property->_get_key_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - } else { - yyerror("reference to non-existent MAKE_MAP_PROPERTY: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - } - } -} -#line 4343 "built/tmp/cppBison.yxx.c" - break; - - case 38: /* declaration: KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 862 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - - } else { - CPPMakeProperty *make_property; - make_property = new CPPMakeProperty((yyvsp[-6].u.identifier), CPPMakeProperty::T_normal, - current_scope, (yylsp[-8]).file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); - } -} -#line 4369 "built/tmp/cppBison.yxx.c" - break; - - case 39: /* declaration: KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 884 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - - } else { - CPPMakeProperty *make_property; - make_property = new CPPMakeProperty((yyvsp[-10].u.identifier), CPPMakeProperty::T_normal, - current_scope, (yylsp[-12]).file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = (yyvsp[-8].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + (yyvsp[-8].u.identifier)->get_fully_scoped_name(), (yylsp[-8])); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - CPPDeclaration *setter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid setter: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *clearer = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (clearer == nullptr || clearer->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid clear method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - } else { - make_property->_clear_function = clearer->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-12])); - } -} -#line 4409 "built/tmp/cppBison.yxx.c" - break; - - case 40: /* declaration: KW_MAKE_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 920 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + (yyvsp[-4].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - length_getter = nullptr; - } - - CPPDeclaration *element_getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (element_getter == nullptr || element_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid element method: " + (yyvsp[-2].u.identifier)->get_fully_scoped_name(), (yylsp[-4])); - element_getter = nullptr; - } - - if (length_getter != nullptr && element_getter != nullptr) { - CPPMakeSeq *make_seq = new CPPMakeSeq((yyvsp[-6].u.identifier), - length_getter->as_function_group(), - element_getter->as_function_group(), - current_scope, (yylsp[-8]).file); - current_scope->add_declaration(make_seq, global_scope, current_lexer, (yylsp[-8])); - } -} -#line 4435 "built/tmp/cppBison.yxx.c" - break; - - case 41: /* declaration: KW_STATIC_ASSERT '(' const_expr ',' string_literal ')' ';' */ -#line 942 "dtool/src/cppparser/cppBison.yxx" -{ - CPPExpression::Result result = (yyvsp[-4].u.expr)->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("static_assert requires a constant expression", (yylsp[-4])); - } else if (!result.as_boolean()) { - stringstream str; - str << *(yyvsp[-2].u.expr); - yywarning("static_assert failed: " + str.str(), (yylsp[-4])); - } -} -#line 4450 "built/tmp/cppBison.yxx.c" - break; - - case 42: /* declaration: KW_STATIC_ASSERT '(' const_expr ')' ';' */ -#line 953 "dtool/src/cppparser/cppBison.yxx" -{ - // This alternative version of static_assert was introduced in C++17. - CPPExpression::Result result = (yyvsp[-2].u.expr)->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("static_assert requires a constant expression", (yylsp[-2])); - } else if (!result.as_boolean()) { - yywarning("static_assert failed", (yylsp[-2])); - } -} -#line 4464 "built/tmp/cppBison.yxx.c" - break; - - case 43: /* $@3: %empty */ -#line 966 "dtool/src/cppparser/cppBison.yxx" -{ - CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("temp"), - V_public); - push_scope(new_scope); -} -#line 4474 "built/tmp/cppBison.yxx.c" - break; - - case 44: /* friend_declaration: KW_FRIEND $@3 declaration */ -#line 972 "dtool/src/cppparser/cppBison.yxx" -{ - delete current_scope; - pop_scope(); -} -#line 4483 "built/tmp/cppBison.yxx.c" - break; - - case 45: /* storage_class: empty */ -#line 981 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = 0; -} -#line 4491 "built/tmp/cppBison.yxx.c" - break; - - case 46: /* storage_class: KW_CONST storage_class */ -#line 985 "dtool/src/cppparser/cppBison.yxx" -{ - // This isn't really a storage class, but it helps with parsing. - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_const; -} -#line 4500 "built/tmp/cppBison.yxx.c" - break; - - case 47: /* storage_class: KW_EXTERN storage_class */ -#line 990 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extern; -} -#line 4508 "built/tmp/cppBison.yxx.c" - break; - - case 48: /* storage_class: KW_EXTERN SIMPLE_STRING storage_class */ -#line 994 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extern; - if ((yyvsp[-1].str) == "C") { - (yyval.u.integer) |= (int)CPPInstance::SC_c_binding; - } else if ((yyvsp[-1].str) == "C++") { - (yyval.u.integer) &= ~(int)CPPInstance::SC_c_binding; - } else { - yywarning("Ignoring unknown linkage type \"" + (yyvsp[-1].str) + "\"", (yylsp[-1])); - } -} -#line 4523 "built/tmp/cppBison.yxx.c" - break; - - case 49: /* storage_class: KW_STATIC storage_class */ -#line 1005 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_static; -} -#line 4531 "built/tmp/cppBison.yxx.c" - break; - - case 50: /* storage_class: KW_INLINE storage_class */ -#line 1009 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_inline; -} -#line 4539 "built/tmp/cppBison.yxx.c" - break; - - case 51: /* storage_class: KW_VIRTUAL storage_class */ -#line 1013 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_virtual; -} -#line 4547 "built/tmp/cppBison.yxx.c" - break; - - case 52: /* storage_class: KW_EXPLICIT storage_class */ -#line 1017 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_explicit; -} -#line 4555 "built/tmp/cppBison.yxx.c" - break; - - case 53: /* storage_class: KW_EXPLICIT_LPAREN const_expr ')' storage_class */ -#line 1021 "dtool/src/cppparser/cppBison.yxx" -{ - CPPExpression::Result result = (yyvsp[-2].u.expr)->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("explicit() requires a constant expression", (yylsp[-2])); - } else if (result.as_boolean()) { - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_explicit; - } -} -#line 4568 "built/tmp/cppBison.yxx.c" - break; - - case 54: /* storage_class: KW_REGISTER storage_class */ -#line 1030 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_register; -} -#line 4576 "built/tmp/cppBison.yxx.c" - break; - - case 55: /* storage_class: KW_VOLATILE storage_class */ -#line 1034 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_volatile; -} -#line 4584 "built/tmp/cppBison.yxx.c" - break; - - case 56: /* storage_class: KW_MUTABLE storage_class */ -#line 1038 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_mutable; -} -#line 4592 "built/tmp/cppBison.yxx.c" - break; - - case 57: /* storage_class: KW_CONSTEVAL storage_class */ -#line 1042 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_consteval; -} -#line 4600 "built/tmp/cppBison.yxx.c" - break; - - case 58: /* storage_class: KW_CONSTEXPR storage_class */ -#line 1046 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_constexpr; -} -#line 4608 "built/tmp/cppBison.yxx.c" - break; - - case 59: /* storage_class: KW_CONSTINIT storage_class */ -#line 1050 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_constinit; -} -#line 4616 "built/tmp/cppBison.yxx.c" - break; - - case 60: /* storage_class: KW_BLOCKING storage_class */ -#line 1054 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_blocking; -} -#line 4624 "built/tmp/cppBison.yxx.c" - break; - - case 61: /* storage_class: KW_EXTENSION storage_class */ -#line 1058 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extension; -} -#line 4632 "built/tmp/cppBison.yxx.c" - break; - - case 62: /* storage_class: KW_THREAD_LOCAL storage_class */ -#line 1062 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_thread_local; -} -#line 4640 "built/tmp/cppBison.yxx.c" - break; - - case 63: /* optional_attributes: empty */ -#line 1069 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = CPPAttributeList(); -} -#line 4648 "built/tmp/cppBison.yxx.c" - break; - - case 64: /* optional_attributes: ATTR_LEFT attribute_specifiers ATTR_RIGHT optional_attributes */ -#line 1073 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = (yyvsp[-2].attr_list); - (yyval.attr_list).add_attributes_from((yyvsp[0].attr_list)); -} -#line 4657 "built/tmp/cppBison.yxx.c" - break; - - case 65: /* optional_attributes: ATTR_LEFT KW_USING name ':' attribute_specifiers ATTR_RIGHT optional_attributes */ -#line 1078 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = (yyvsp[-2].attr_list); - for (CPPAttributeList::Attribute &attr : (yyval.attr_list)._attributes) { - attr._ident->prepend((yyvsp[-4].u.identifier)); - } - (yyval.attr_list).add_attributes_from((yyvsp[0].attr_list)); -} -#line 4669 "built/tmp/cppBison.yxx.c" - break; - - case 66: /* optional_attributes: KW_ALIGNAS '(' const_expr ')' optional_attributes */ -#line 1086 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = (yyvsp[0].attr_list); - (yyval.attr_list).add_alignas((yyvsp[-2].u.expr)->as_expression()); -} -#line 4678 "built/tmp/cppBison.yxx.c" - break; - - case 67: /* optional_attributes: KW_ALIGNAS '(' type_decl ')' optional_attributes */ -#line 1091 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = (yyvsp[0].attr_list); - (yyval.attr_list).add_alignas((yyvsp[-2].u.decl)->as_type()); -} -#line 4687 "built/tmp/cppBison.yxx.c" - break; - - case 68: /* attribute_specifiers: attribute_specifier */ -#line 1099 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = (yyvsp[0].attr_list); -} -#line 4695 "built/tmp/cppBison.yxx.c" - break; - - case 69: /* attribute_specifiers: attribute_specifier ',' attribute_specifiers */ -#line 1103 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = (yyvsp[-2].attr_list); - (yyval.attr_list).add_attributes_from((yyvsp[0].attr_list)); -} -#line 4704 "built/tmp/cppBison.yxx.c" - break; - - case 70: /* attribute_specifier: name */ -#line 1111 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = CPPAttributeList(); - (yyval.attr_list).add_attribute((yyvsp[0].u.identifier)); -} -#line 4713 "built/tmp/cppBison.yxx.c" - break; - - case 71: /* attribute_specifier: name '(' formal_parameter_list ')' */ -#line 1116 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.attr_list) = CPPAttributeList(); - (yyval.attr_list).add_attribute((yyvsp[-3].u.identifier)); -} -#line 4722 "built/tmp/cppBison.yxx.c" - break; - - case 72: /* $@4: %empty */ -#line 1124 "dtool/src/cppparser/cppBison.yxx" -{ - // We don't need to push/pop type, because we can't nest - // type_like_declaration. - if ((yyvsp[0].u.decl)->as_type_declaration()) { - current_type = (yyvsp[0].u.decl)->as_type_declaration()->_type; - } else { - current_type = (yyvsp[0].u.decl)->as_type(); - } - push_storage_class((yyvsp[-1].u.integer)); -} -#line 4737 "built/tmp/cppBison.yxx.c" - break; - - case 73: /* type_like_declaration: storage_class var_type_decl $@4 multiple_instance_identifiers */ -#line 1135 "dtool/src/cppparser/cppBison.yxx" -{ - pop_storage_class(); -} -#line 4745 "built/tmp/cppBison.yxx.c" - break; - - case 74: /* type_like_declaration: storage_class type_decl ';' */ -#line 1140 "dtool/src/cppparser/cppBison.yxx" -{ - // We don't really care about the storage class here. In fact, it's - // not actually legal to define a class or struct using a particular - // storage class, but we require it just to help yacc out in its - // parsing. - - current_scope->add_declaration((yyvsp[-1].u.decl), global_scope, current_lexer, (yylsp[-1])); -} -#line 4758 "built/tmp/cppBison.yxx.c" - break; - - case 75: /* $@5: %empty */ -#line 1149 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[0].u.instance) != nullptr) { - // Push the scope so that the initializers can make use of things defined - // in the class body. - push_scope((yyvsp[0].u.instance)->get_scope(current_scope, global_scope)); - (yyvsp[0].u.instance)->_storage_class |= (current_storage_class | (yyvsp[-1].u.integer)); - } -} -#line 4771 "built/tmp/cppBison.yxx.c" - break; - - case 76: /* type_like_declaration: storage_class constructor_prototype $@5 maybe_initialize_or_constructor_body */ -#line 1158 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-2].u.instance) != nullptr) { - pop_scope(); - current_scope->add_declaration((yyvsp[-2].u.instance), global_scope, current_lexer, (yylsp[-2])); - (yyvsp[-2].u.instance)->set_initializer((yyvsp[0].u.expr)); - } -} -#line 4783 "built/tmp/cppBison.yxx.c" - break; - - case 77: /* type_like_declaration: storage_class function_prototype maybe_initialize_or_function_body */ -#line 1166 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-1].u.instance) != nullptr) { - (yyvsp[-1].u.instance)->_storage_class |= (current_storage_class | (yyvsp[-2].u.integer)); - current_scope->add_declaration((yyvsp[-1].u.instance), global_scope, current_lexer, (yylsp[-1])); - (yyvsp[-1].u.instance)->set_initializer((yyvsp[0].u.expr)); - } -} -#line 4795 "built/tmp/cppBison.yxx.c" - break; - - case 79: /* multiple_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body */ -#line 1182 "dtool/src/cppparser/cppBison.yxx" -{ - if (current_storage_class & CPPInstance::SC_const) { - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - } - (yyvsp[-1].u.inst_ident)->add_attributes(current_attributes); - CPPInstance *inst = new CPPInstance(current_type, (yyvsp[-1].u.inst_ident), - current_storage_class, - (yylsp[-1]).file); - inst->set_initializer((yyvsp[0].u.expr)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-1])); -} -#line 4811 "built/tmp/cppBison.yxx.c" - break; - - case 80: /* multiple_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' multiple_instance_identifiers */ -#line 1194 "dtool/src/cppparser/cppBison.yxx" -{ - if (current_storage_class & CPPInstance::SC_const) { - (yyvsp[-3].u.inst_ident)->add_modifier(IIT_const); - } - (yyvsp[-3].u.inst_ident)->add_attributes(current_attributes); - CPPInstance *inst = new CPPInstance(current_type, (yyvsp[-3].u.inst_ident), - current_storage_class, - (yylsp[-3]).file); - inst->set_initializer((yyvsp[-2].u.expr)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-3])); -} -#line 4827 "built/tmp/cppBison.yxx.c" - break; - - case 81: /* $@6: %empty */ -#line 1210 "dtool/src/cppparser/cppBison.yxx" -{ - // We don't need to push/pop type, because we can't nest - // multiple_var_declarations. - if ((yyvsp[0].u.decl)->as_type_declaration()) { - current_type = (yyvsp[0].u.decl)->as_type_declaration()->_type; - } else { - current_type = (yyvsp[0].u.decl)->as_type(); - } - push_storage_class((yyvsp[-1].u.integer)); -} -#line 4842 "built/tmp/cppBison.yxx.c" - break; - - case 82: /* typedef_declaration: storage_class var_type_decl $@6 typedef_instance_identifiers */ -#line 1221 "dtool/src/cppparser/cppBison.yxx" -{ - pop_storage_class(); -} -#line 4850 "built/tmp/cppBison.yxx.c" - break; - - case 83: /* typedef_declaration: storage_class function_prototype maybe_initialize_or_function_body */ -#line 1225 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-1].u.instance) != nullptr) { - CPPInstance *inst = (yyvsp[-1].u.instance)->as_instance(); - if (inst != nullptr) { - inst->_storage_class |= (current_storage_class | (yyvsp[-2].u.integer)); - current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-1])); - CPPTypedefType *typedef_type = new CPPTypedefType(inst->_type, inst->_ident, current_scope, inst->_attributes); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-1])); - } - } -} -#line 4866 "built/tmp/cppBison.yxx.c" - break; - - case 84: /* typedef_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body */ -#line 1240 "dtool/src/cppparser/cppBison.yxx" -{ - if (current_storage_class & CPPInstance::SC_const) { - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - } - (yyvsp[-1].u.inst_ident)->add_attributes(current_attributes); - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-1].u.inst_ident), current_scope, (yylsp[-1]).file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-1])); -} -#line 4880 "built/tmp/cppBison.yxx.c" - break; - - case 85: /* typedef_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' typedef_instance_identifiers */ -#line 1250 "dtool/src/cppparser/cppBison.yxx" -{ - if (current_storage_class & CPPInstance::SC_const) { - (yyvsp[-3].u.inst_ident)->add_modifier(IIT_const); - } - (yyvsp[-3].u.inst_ident)->add_attributes(current_attributes); - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-3].u.inst_ident), current_scope, (yylsp[-3]).file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-3])); -} -#line 4894 "built/tmp/cppBison.yxx.c" - break; - - case 86: /* $@7: %empty */ -#line 1265 "dtool/src/cppparser/cppBison.yxx" -{ - // Create a scope for this function. - CPPScope *scope = new CPPScope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope), - (yyvsp[-1].u.identifier)->_names.back(), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} -#line 4911 "built/tmp/cppBison.yxx.c" - break; - - case 87: /* constructor_prototype: IDENTIFIER '(' $@7 function_parameter_list ')' function_post optional_attributes */ -#line 1278 "dtool/src/cppparser/cppBison.yxx" -{ - CPPScope *scope = (yyvsp[-6].u.identifier)->get_scope(current_scope, global_scope); - CPPType *type; - std::string simple_name = (yyvsp[-6].u.identifier)->get_simple_name(); - if (!simple_name.empty() && simple_name[0] == '~') { - // A destructor has no return type. - type = new CPPSimpleType(CPPSimpleType::T_void); - } - else if (scope != nullptr && simple_name == scope->get_simple_name()) { - // Neither does a constructor. - type = new CPPSimpleType(CPPSimpleType::T_void); - } - else { - // This isn't a constructor, so it has an implicit return type of - // int. - yywarning("function has no return type, assuming int", (yylsp[-6])); - type = new CPPSimpleType(CPPSimpleType::T_int); - } - pop_scope(); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[-6].u.identifier)); - ii->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); - ii->add_attributes(current_attributes); - - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-6]).file); -} -#line 4942 "built/tmp/cppBison.yxx.c" - break; - - case 88: /* $@8: %empty */ -#line 1307 "dtool/src/cppparser/cppBison.yxx" -{ - // Create a scope for this function. - CPPScope *scope = new CPPScope((yyvsp[-2].u.identifier)->get_scope(current_scope, global_scope), - (yyvsp[-2].u.identifier)->_names.back(), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} -#line 4959 "built/tmp/cppBison.yxx.c" - break; - - case 89: /* constructor_prototype: TYPENAME_IDENTIFIER '(' IDENTIFIER ')' '(' $@8 function_parameter_list ')' function_post optional_attributes */ -#line 1320 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); - CPPType *type = (yyvsp[-9].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[-9].u.identifier)->get_fully_scoped_name(), (yylsp[-9])); - } - assert(type != nullptr); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[-7].u.identifier)); - ii->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); - ii->add_attributes(current_attributes); - - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-9]).file); -} -#line 4978 "built/tmp/cppBison.yxx.c" - break; - - case 90: /* $@9: %empty */ -#line 1335 "dtool/src/cppparser/cppBison.yxx" -{ - // Create a scope for this function. - CPPScope *scope = new CPPScope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope), - (yyvsp[-1].u.identifier)->_names.back(), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} -#line 4995 "built/tmp/cppBison.yxx.c" - break; - - case 91: /* constructor_prototype: TYPENAME_IDENTIFIER '(' $@9 function_parameter_list ')' function_post optional_attributes */ -#line 1348 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); - CPPType *type; - if ((yyvsp[-6].u.identifier)->get_simple_name() == current_scope->get_simple_name()) { - // This is a constructor, and has no return. - type = new CPPSimpleType(CPPSimpleType::T_void); - } else { - // This isn't a constructor, so it has an implicit return type of - // int. - type = new CPPSimpleType(CPPSimpleType::T_int); - } - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier((yyvsp[-6].u.identifier)); - ii->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); - ii->add_attributes(current_attributes); - - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-6]).file); -} -#line 5018 "built/tmp/cppBison.yxx.c" - break; - - case 92: /* $@10: %empty */ -#line 1372 "dtool/src/cppparser/cppBison.yxx" -{ - push_scope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope)); -} -#line 5026 "built/tmp/cppBison.yxx.c" - break; - - case 93: /* function_prototype: '~' name '(' $@10 function_parameter_list ')' function_post optional_attributes */ -#line 1376 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); - if ((yyvsp[-6].u.identifier)->is_scoped()) { - yyerror("Invalid destructor name: ~" + (yyvsp[-6].u.identifier)->get_fully_scoped_name(), (yylsp[-6])); - } else { - CPPIdentifier *ident = - new CPPIdentifier("~" + (yyvsp[-6].u.identifier)->get_simple_name(), (yylsp[-6])); - delete (yyvsp[-6].u.identifier); - - CPPType *type; - type = new CPPSimpleType(CPPSimpleType::T_void); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident); - ii->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); - ii->add_attributes(current_attributes); - - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-6]).file); - } -} -#line 5050 "built/tmp/cppBison.yxx.c" - break; - - case 94: /* $@11: %empty */ -#line 1403 "dtool/src/cppparser/cppBison.yxx" -{ - push_scope((yyvsp[-2].u.inst_ident)->get_scope(current_scope, global_scope)); -} -#line 5058 "built/tmp/cppBison.yxx.c" - break; - - case 95: /* function_prototype: TYPENAME_IDENTIFIER '(' '*' instance_identifier ')' '(' $@11 function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 1407 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); - CPPType *type = (yyvsp[-11].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[-11].u.identifier)->get_fully_scoped_name(), (yylsp[-11])); - } - assert(type != nullptr); - - CPPInstanceIdentifier *ii = (yyvsp[-8].u.inst_ident); - ii->add_modifier(IIT_pointer); - ii->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), nullptr, (yyvsp[-1].attr_list)); - ii->add_attributes(current_attributes); - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-11]).file); -} -#line 5077 "built/tmp/cppBison.yxx.c" - break; - - case 96: /* $@12: %empty */ -#line 1422 "dtool/src/cppparser/cppBison.yxx" -{ - push_scope((yyvsp[-2].u.inst_ident)->get_scope(current_scope, global_scope)); -} -#line 5085 "built/tmp/cppBison.yxx.c" - break; - - case 97: /* function_prototype: TYPENAME_IDENTIFIER '(' SCOPING '*' instance_identifier ')' '(' $@12 function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 1426 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); - CPPType *type = (yyvsp[-12].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[-12].u.identifier)->get_fully_scoped_name(), (yylsp[-12])); - } - assert(type != nullptr); - - CPPInstanceIdentifier *ii = (yyvsp[-8].u.inst_ident); - ii->add_scoped_pointer_modifier((yyvsp[-10].u.identifier)); - ii->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), nullptr, (yyvsp[-1].attr_list)); - ii->add_attributes(current_attributes); - (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-12]).file); -} -#line 5104 "built/tmp/cppBison.yxx.c" - break; - - case 98: /* $@13: %empty */ -#line 1443 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-3].u.identifier) != nullptr) { - push_scope((yyvsp[-3].u.identifier)->get_scope(current_scope, global_scope)); - } -} -#line 5114 "built/tmp/cppBison.yxx.c" - break; - - case 99: /* function_prototype: KW_OPERATOR type not_paren_formal_parameter_identifier '(' $@13 function_parameter_list ')' function_post */ -#line 1449 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-7].u.identifier) != nullptr) { - pop_scope(); - } - - // We use formal_parameter_identifier, because that can match a type - // name with or without an identifier, but especially without, which - // is what follows the keyword "operator" in a typecast function. - // As an added bonus, the type of the formal_parameter will be the - // typecast type, i.e. the return type of the typecast function. - - // We give typecast operators the name "operator typecast ", - // where is a simple name of the type to be typecast. Use - // the method's return type to determine the full type description. - string name = "operator typecast " + (yyvsp[-6].u.type)->get_simple_name(); - CPPIdentifier *ident = (yyvsp[-7].u.identifier); - if (ident == nullptr) { - ident = new CPPIdentifier(name, (yylsp[-6])); - } else { - ident->add_name(name); - } - (yyval.u.instance) = CPPInstance::make_typecast_function - (new CPPInstance((yyvsp[-6].u.type), (yyvsp[-5].u.inst_ident), 0, (yylsp[-5]).file), ident, (yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); - (yyval.u.instance)->_attributes.add_attributes_from(current_attributes); -} -#line 5144 "built/tmp/cppBison.yxx.c" - break; - - case 100: /* $@14: %empty */ -#line 1475 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-4].u.identifier) != nullptr) { - push_scope((yyvsp[-4].u.identifier)->get_scope(current_scope, global_scope)); - } -} -#line 5154 "built/tmp/cppBison.yxx.c" - break; - - case 101: /* function_prototype: KW_OPERATOR KW_CONST type not_paren_formal_parameter_identifier '(' $@14 function_parameter_list ')' function_post */ -#line 1481 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-8].u.identifier) != nullptr) { - pop_scope(); - } - - CPPIdentifier *ident = (yyvsp[-8].u.identifier); - if (ident == nullptr) { - ident = new CPPIdentifier("operator typecast", (yylsp[-5])); - } else { - ident->add_name("operator typecast"); - } - (yyvsp[-5].u.inst_ident)->add_modifier(IIT_const); - (yyvsp[-5].u.inst_ident)->add_attributes(current_attributes); - (yyval.u.instance) = CPPInstance::make_typecast_function - (new CPPInstance((yyvsp[-6].u.type), (yyvsp[-5].u.inst_ident), 0, (yylsp[-5]).file), ident, (yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); -} -#line 5175 "built/tmp/cppBison.yxx.c" - break; - - case 102: /* function_prototype: IDENTIFIER */ -#line 1502 "dtool/src/cppparser/cppBison.yxx" -{ - CPPDeclaration *decl = - (yyvsp[0].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); - if (decl != nullptr) { - (yyval.u.instance) = decl->as_instance(); - } else { - (yyval.u.instance) = nullptr; - } -} -#line 5189 "built/tmp/cppBison.yxx.c" - break; - - case 103: /* function_post: empty */ -#line 1515 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = 0; -} -#line 5197 "built/tmp/cppBison.yxx.c" - break; - - case 104: /* function_post: function_post KW_CONST */ -#line 1519 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_const_method; -} -#line 5205 "built/tmp/cppBison.yxx.c" - break; - - case 105: /* function_post: function_post KW_VOLATILE */ -#line 1523 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_volatile_method; -} -#line 5213 "built/tmp/cppBison.yxx.c" - break; - - case 106: /* function_post: function_post KW_NOEXCEPT */ -#line 1527 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_noexcept; -} -#line 5221 "built/tmp/cppBison.yxx.c" - break; - - case 107: /* function_post: function_post KW_NOEXCEPT_LPAREN const_expr ')' */ -#line 1531 "dtool/src/cppparser/cppBison.yxx" -{ - CPPExpression::Result result = (yyvsp[-1].u.expr)->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("noexcept() requires a constant expression", (yylsp[-1])); - } else if (result.as_boolean()) { - (yyval.u.integer) = (yyvsp[-3].u.integer) | (int)CPPFunctionType::F_noexcept; - } -} -#line 5234 "built/tmp/cppBison.yxx.c" - break; - - case 108: /* function_post: function_post KW_FINAL */ -#line 1540 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_final; -} -#line 5242 "built/tmp/cppBison.yxx.c" - break; - - case 109: /* function_post: function_post KW_OVERRIDE */ -#line 1544 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_override; -} -#line 5250 "built/tmp/cppBison.yxx.c" - break; - - case 110: /* function_post: function_post '&' */ -#line 1548 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_lvalue_method; -} -#line 5258 "built/tmp/cppBison.yxx.c" - break; - - case 111: /* function_post: function_post ANDAND */ -#line 1552 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_rvalue_method; -} -#line 5266 "built/tmp/cppBison.yxx.c" - break; - - case 112: /* function_post: function_post KW_MUTABLE */ -#line 1556 "dtool/src/cppparser/cppBison.yxx" -{ - // Used for lambdas, currently ignored. - (yyval.u.integer) = (yyvsp[-1].u.integer); -} -#line 5275 "built/tmp/cppBison.yxx.c" - break; - - case 113: /* function_post: function_post KW_CONSTEXPR */ -#line 1561 "dtool/src/cppparser/cppBison.yxx" -{ - // Used for lambdas in C++17, currently ignored. - (yyval.u.integer) = (yyvsp[-1].u.integer); -} -#line 5284 "built/tmp/cppBison.yxx.c" - break; - - case 114: /* function_post: function_post KW_THROW '(' ')' */ -#line 1566 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-3].u.integer); -} -#line 5292 "built/tmp/cppBison.yxx.c" - break; - - case 115: /* function_post: function_post KW_THROW '(' name ')' */ -#line 1570 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-4].u.integer); -} -#line 5300 "built/tmp/cppBison.yxx.c" - break; - - case 116: /* function_post: function_post KW_THROW '(' name ELLIPSIS ')' */ -#line 1574 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.integer) = (yyvsp[-5].u.integer); -} -#line 5308 "built/tmp/cppBison.yxx.c" - break; - - case 117: /* function_operator: '!' */ -#line 1581 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "!"; -} -#line 5316 "built/tmp/cppBison.yxx.c" - break; - - case 118: /* function_operator: '~' */ -#line 1585 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "~"; -} -#line 5324 "built/tmp/cppBison.yxx.c" - break; - - case 119: /* function_operator: '*' */ -#line 1589 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "*"; -} -#line 5332 "built/tmp/cppBison.yxx.c" - break; - - case 120: /* function_operator: '/' */ -#line 1593 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "/"; -} -#line 5340 "built/tmp/cppBison.yxx.c" - break; - - case 121: /* function_operator: '%' */ -#line 1597 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "%"; -} -#line 5348 "built/tmp/cppBison.yxx.c" - break; - - case 122: /* function_operator: '+' */ -#line 1601 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "+"; -} -#line 5356 "built/tmp/cppBison.yxx.c" - break; - - case 123: /* function_operator: '-' */ -#line 1605 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "-"; -} -#line 5364 "built/tmp/cppBison.yxx.c" - break; - - case 124: /* function_operator: '|' */ -#line 1609 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "|"; -} -#line 5372 "built/tmp/cppBison.yxx.c" - break; - - case 125: /* function_operator: '&' */ -#line 1613 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "&"; -} -#line 5380 "built/tmp/cppBison.yxx.c" - break; - - case 126: /* function_operator: '^' */ -#line 1617 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "^"; -} -#line 5388 "built/tmp/cppBison.yxx.c" - break; - - case 127: /* function_operator: OROR */ -#line 1621 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "||"; -} -#line 5396 "built/tmp/cppBison.yxx.c" - break; - - case 128: /* function_operator: ANDAND */ -#line 1625 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "&&"; -} -#line 5404 "built/tmp/cppBison.yxx.c" - break; - - case 129: /* function_operator: EQCOMPARE */ -#line 1629 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "=="; -} -#line 5412 "built/tmp/cppBison.yxx.c" - break; - - case 130: /* function_operator: NECOMPARE */ -#line 1633 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "!="; -} -#line 5420 "built/tmp/cppBison.yxx.c" - break; - - case 131: /* function_operator: LECOMPARE */ -#line 1637 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "<="; -} -#line 5428 "built/tmp/cppBison.yxx.c" - break; - - case 132: /* function_operator: GECOMPARE */ -#line 1641 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = ">="; -} -#line 5436 "built/tmp/cppBison.yxx.c" - break; - - case 133: /* function_operator: '<' */ -#line 1645 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "<"; -} -#line 5444 "built/tmp/cppBison.yxx.c" - break; - - case 134: /* function_operator: '>' */ -#line 1649 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = ">"; -} -#line 5452 "built/tmp/cppBison.yxx.c" - break; - - case 135: /* function_operator: SPACESHIP */ -#line 1653 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "<=>"; -} -#line 5460 "built/tmp/cppBison.yxx.c" - break; - - case 136: /* function_operator: LSHIFT */ -#line 1657 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "<<"; -} -#line 5468 "built/tmp/cppBison.yxx.c" - break; - - case 137: /* function_operator: RSHIFT */ -#line 1661 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = ">>"; -} -#line 5476 "built/tmp/cppBison.yxx.c" - break; - - case 138: /* function_operator: '=' */ -#line 1665 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "="; -} -#line 5484 "built/tmp/cppBison.yxx.c" - break; - - case 139: /* function_operator: ',' */ -#line 1669 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = ","; -} -#line 5492 "built/tmp/cppBison.yxx.c" - break; - - case 140: /* function_operator: PLUSPLUS */ -#line 1673 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "++"; -} -#line 5500 "built/tmp/cppBison.yxx.c" - break; - - case 141: /* function_operator: MINUSMINUS */ -#line 1677 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "--"; -} -#line 5508 "built/tmp/cppBison.yxx.c" - break; - - case 142: /* function_operator: TIMESEQUAL */ -#line 1681 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "*="; -} -#line 5516 "built/tmp/cppBison.yxx.c" - break; - - case 143: /* function_operator: DIVIDEEQUAL */ -#line 1685 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "/="; -} -#line 5524 "built/tmp/cppBison.yxx.c" - break; - - case 144: /* function_operator: MODEQUAL */ -#line 1689 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "%="; -} -#line 5532 "built/tmp/cppBison.yxx.c" - break; - - case 145: /* function_operator: PLUSEQUAL */ -#line 1693 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "+="; -} -#line 5540 "built/tmp/cppBison.yxx.c" - break; - - case 146: /* function_operator: MINUSEQUAL */ -#line 1697 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "-="; -} -#line 5548 "built/tmp/cppBison.yxx.c" - break; - - case 147: /* function_operator: OREQUAL */ -#line 1701 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "|="; -} -#line 5556 "built/tmp/cppBison.yxx.c" - break; - - case 148: /* function_operator: ANDEQUAL */ -#line 1705 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "&="; -} -#line 5564 "built/tmp/cppBison.yxx.c" - break; - - case 149: /* function_operator: XOREQUAL */ -#line 1709 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "^="; -} -#line 5572 "built/tmp/cppBison.yxx.c" - break; - - case 150: /* function_operator: LSHIFTEQUAL */ -#line 1713 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "<<="; -} -#line 5580 "built/tmp/cppBison.yxx.c" - break; - - case 151: /* function_operator: RSHIFTEQUAL */ -#line 1717 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = ">>="; -} -#line 5588 "built/tmp/cppBison.yxx.c" - break; - - case 152: /* function_operator: POINTSAT */ -#line 1721 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "->"; -} -#line 5596 "built/tmp/cppBison.yxx.c" - break; - - case 153: /* function_operator: '[' ']' */ -#line 1725 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "[]"; -} -#line 5604 "built/tmp/cppBison.yxx.c" - break; - - case 154: /* function_operator: '(' ')' */ -#line 1729 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "()"; -} -#line 5612 "built/tmp/cppBison.yxx.c" - break; - - case 155: /* function_operator: KW_NEW */ -#line 1733 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "new"; -} -#line 5620 "built/tmp/cppBison.yxx.c" - break; - - case 156: /* function_operator: KW_DELETE */ -#line 1737 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.str) = "delete"; -} -#line 5628 "built/tmp/cppBison.yxx.c" - break; - - case 161: /* $@15: %empty */ -#line 1751 "dtool/src/cppparser/cppBison.yxx" -{ - push_scope(new CPPTemplateScope(current_scope)); -} -#line 5636 "built/tmp/cppBison.yxx.c" - break; - - case 162: /* template_declaration: KW_TEMPLATE $@15 '<' template_formal_parameters '>' more_template_declaration */ -#line 1755 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); -} -#line 5644 "built/tmp/cppBison.yxx.c" - break; - - case 167: /* template_nonempty_formal_parameters: template_formal_parameter */ -#line 1769 "dtool/src/cppparser/cppBison.yxx" -{ - CPPTemplateScope *ts = current_scope->as_template_scope(); - assert(ts != nullptr); - ts->add_template_parameter((yyvsp[0].u.decl)); -} -#line 5654 "built/tmp/cppBison.yxx.c" - break; - - case 168: /* template_nonempty_formal_parameters: template_nonempty_formal_parameters ',' template_formal_parameter */ -#line 1775 "dtool/src/cppparser/cppBison.yxx" -{ - CPPTemplateScope *ts = current_scope->as_template_scope(); - assert(ts != nullptr); - ts->add_template_parameter((yyvsp[0].u.decl)); -} -#line 5664 "built/tmp/cppBison.yxx.c" - break; - - case 171: /* template_formal_parameter: typename_keyword */ -#line 1789 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter(nullptr)); -} -#line 5672 "built/tmp/cppBison.yxx.c" - break; - - case 172: /* template_formal_parameter: typename_keyword name */ -#line 1793 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[0].u.identifier))); -} -#line 5680 "built/tmp/cppBison.yxx.c" - break; - - case 173: /* template_formal_parameter: typename_keyword name '=' full_type */ -#line 1797 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[-2].u.identifier), (yyvsp[0].u.type))); -} -#line 5688 "built/tmp/cppBison.yxx.c" - break; - - case 174: /* template_formal_parameter: typename_keyword ELLIPSIS */ -#line 1801 "dtool/src/cppparser/cppBison.yxx" -{ - CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter(nullptr); - ctp->_packed = true; - (yyval.u.decl) = CPPType::new_type(ctp); -} -#line 5698 "built/tmp/cppBison.yxx.c" - break; - - case 175: /* template_formal_parameter: typename_keyword ELLIPSIS name */ -#line 1807 "dtool/src/cppparser/cppBison.yxx" -{ - CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((yyvsp[0].u.identifier)); - ctp->_packed = true; - (yyval.u.decl) = CPPType::new_type(ctp); -} -#line 5708 "built/tmp/cppBison.yxx.c" - break; - - case 176: /* template_formal_parameter: template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize */ -#line 1813 "dtool/src/cppparser/cppBison.yxx" -{ - CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - inst->set_initializer((yyvsp[0].u.expr)); - (yyval.u.decl) = inst; -} -#line 5718 "built/tmp/cppBison.yxx.c" - break; - - case 177: /* template_formal_parameter: KW_CONST template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize */ -#line 1819 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - inst->set_initializer((yyvsp[0].u.expr)); - (yyval.u.decl) = inst; -} -#line 5729 "built/tmp/cppBison.yxx.c" - break; - - case 178: /* template_formal_parameter: template_formal_parameter_type parameter_pack_identifier */ -#line 1826 "dtool/src/cppparser/cppBison.yxx" -{ - CPPInstance *inst = new CPPInstance((yyvsp[-1].u.type), (yyvsp[0].u.inst_ident), 0, (yylsp[0]).file); - (yyval.u.decl) = inst; -} -#line 5738 "built/tmp/cppBison.yxx.c" - break; - - case 179: /* template_formal_parameter: KW_CONST template_formal_parameter_type parameter_pack_identifier */ -#line 1831 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance((yyvsp[-1].u.type), (yyvsp[0].u.inst_ident), 0, (yylsp[0]).file); - (yyval.u.decl) = inst; -} -#line 5748 "built/tmp/cppBison.yxx.c" - break; - - case 180: /* template_formal_parameter: KW_VOLATILE template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize */ -#line 1837 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_volatile); - CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - inst->set_initializer((yyvsp[0].u.expr)); - (yyval.u.decl) = inst; -} -#line 5759 "built/tmp/cppBison.yxx.c" - break; - - case 181: /* template_formal_parameter: KW_VOLATILE template_formal_parameter_type parameter_pack_identifier */ -#line 1844 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[0].u.inst_ident)->add_modifier(IIT_volatile); - CPPInstance *inst = new CPPInstance((yyvsp[-1].u.type), (yyvsp[0].u.inst_ident), 0, (yylsp[0]).file); - (yyval.u.decl) = inst; -} -#line 5769 "built/tmp/cppBison.yxx.c" - break; - - case 182: /* template_formal_parameter_type: simple_type */ -#line 1853 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); -} -#line 5777 "built/tmp/cppBison.yxx.c" - break; - - case 183: /* template_formal_parameter_type: IDENTIFIER */ -#line 1857 "dtool/src/cppparser/cppBison.yxx" -{ - yywarning("Not a type: " + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); -} -#line 5786 "built/tmp/cppBison.yxx.c" - break; - - case 184: /* template_formal_parameter_type: TYPENAME_IDENTIFIER */ -#line 1862 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - } - assert((yyval.u.type) != nullptr); -} -#line 5798 "built/tmp/cppBison.yxx.c" - break; - - case 185: /* template_formal_parameter_type: TYPEPACK_IDENTIFIER */ -#line 1870 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - } - assert((yyval.u.type) != nullptr); -} -#line 5810 "built/tmp/cppBison.yxx.c" - break; - - case 186: /* instance_identifier: name_no_final optional_attributes */ -#line 1882 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); -} -#line 5818 "built/tmp/cppBison.yxx.c" - break; - - case 187: /* instance_identifier: KW_OPERATOR function_operator optional_attributes */ -#line 1886 "dtool/src/cppparser/cppBison.yxx" -{ - // For an operator function. We implement this simply by building a - // ficticious name for the function; in other respects it's just - // like a regular function. - CPPIdentifier *ident = (yyvsp[-2].u.identifier); - if (ident == nullptr) { - ident = new CPPIdentifier("operator "+(yyvsp[-1].str), (yylsp[-1])); - } else { - ident->_names.push_back("operator "+(yyvsp[-1].str)); - } - - (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident, (yyvsp[0].attr_list)); -} -#line 5836 "built/tmp/cppBison.yxx.c" - break; - - case 188: /* instance_identifier: KW_OPERATOR SIMPLE_STRING IDENTIFIER optional_attributes */ -#line 1900 "dtool/src/cppparser/cppBison.yxx" -{ - // A C++11 literal operator. - if (!(yyvsp[-2].str).empty()) { - yyerror("expected empty string", (yylsp[-2])); - } - CPPIdentifier *ident = (yyvsp[-3].u.identifier); - if (ident == nullptr) { - ident = new CPPIdentifier("operator \"\" "+(yyvsp[-1].u.identifier)->get_simple_name(), (yylsp[-1])); - } else { - ident->_names.push_back("operator \"\" "+(yyvsp[-1].u.identifier)->get_simple_name()); - } - - (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident, (yyvsp[0].attr_list)); -} -#line 5855 "built/tmp/cppBison.yxx.c" - break; - - case 189: /* instance_identifier: KW_CONST instance_identifier */ -#line 1915 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} -#line 5864 "built/tmp/cppBison.yxx.c" - break; - - case 190: /* instance_identifier: KW_VOLATILE instance_identifier */ -#line 1920 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} -#line 5873 "built/tmp/cppBison.yxx.c" - break; - - case 191: /* instance_identifier: '*' optional_attributes instance_identifier */ -#line 1925 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); -} -#line 5882 "built/tmp/cppBison.yxx.c" - break; - - case 192: /* instance_identifier: '&' optional_attributes instance_identifier */ -#line 1930 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); -} -#line 5891 "built/tmp/cppBison.yxx.c" - break; - - case 193: /* instance_identifier: ANDAND optional_attributes instance_identifier */ -#line 1935 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); -} -#line 5900 "built/tmp/cppBison.yxx.c" - break; - - case 194: /* instance_identifier: SCOPING '*' optional_attributes instance_identifier */ -#line 1940 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); -} -#line 5909 "built/tmp/cppBison.yxx.c" - break; - - case 195: /* instance_identifier: instance_identifier '[' optional_const_expr ']' optional_attributes */ -#line 1945 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); -} -#line 5918 "built/tmp/cppBison.yxx.c" - break; - - case 196: /* instance_identifier: '(' instance_identifier ')' */ -#line 1950 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); -} -#line 5927 "built/tmp/cppBison.yxx.c" - break; - - case 197: /* $@16: %empty */ -#line 1955 "dtool/src/cppparser/cppBison.yxx" -{ - // Create a scope for this function (in case it is a function) - CPPScope *scope = new CPPScope((yyvsp[-1].u.inst_ident)->get_scope(current_scope, global_scope), - CPPNameComponent(""), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} -#line 5944 "built/tmp/cppBison.yxx.c" - break; - - case 198: /* instance_identifier: instance_identifier '(' $@16 formal_parameter_list ')' function_post optional_attributes */ -#line 1968 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); - (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); - if ((yyvsp[-3].u.param_list)->is_parameter_expr() && (yyvsp[-1].u.integer) == 0) { - // Oops, this must have been an instance declaration with a - // parameter list, not a function prototype. - (yyval.u.inst_ident)->add_initializer_modifier((yyvsp[-3].u.param_list)); - } - else { - // This was (probably) a function prototype. - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); - } -} -#line 5962 "built/tmp/cppBison.yxx.c" - break; - - case 199: /* instance_identifier_and_maybe_trailing_return_type: instance_identifier maybe_trailing_return_type */ -#line 1986 "dtool/src/cppparser/cppBison.yxx" -{ - // This is handled a bit awkwardly right now. Ideally it'd be wrapped - // up in the instance_identifier rule, but then more needs to happen in - // order to avoid shift/reduce conflicts. - if ((yyvsp[0].u.type) != nullptr) { - (yyvsp[-1].u.inst_ident)->add_trailing_return_type((yyvsp[0].u.type)); - } - (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); -} -#line 5976 "built/tmp/cppBison.yxx.c" - break; - - case 200: /* instance_identifier_and_maybe_trailing_return_type: instance_identifier ':' const_expr */ -#line 1996 "dtool/src/cppparser/cppBison.yxx" -{ - // Bitfield definition. - (yyvsp[-2].u.inst_ident)->_bit_width = (yyvsp[0].u.expr); - (yyval.u.inst_ident) = (yyvsp[-2].u.inst_ident); -} -#line 5986 "built/tmp/cppBison.yxx.c" - break; - - case 201: /* maybe_trailing_return_type: empty */ -#line 2006 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = nullptr; -} -#line 5994 "built/tmp/cppBison.yxx.c" - break; - - case 202: /* maybe_trailing_return_type: POINTSAT predefined_type empty_instance_identifier */ -#line 2010 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); -} -#line 6002 "built/tmp/cppBison.yxx.c" - break; - - case 203: /* maybe_trailing_return_type: POINTSAT KW_CONST predefined_type empty_instance_identifier */ -#line 2014 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); -} -#line 6011 "built/tmp/cppBison.yxx.c" - break; - - case 204: /* maybe_comma_identifier: empty */ -#line 2023 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = nullptr; -} -#line 6019 "built/tmp/cppBison.yxx.c" - break; - - case 205: /* maybe_comma_identifier: ',' IDENTIFIER */ -#line 2027 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 6027 "built/tmp/cppBison.yxx.c" - break; - - case 206: /* function_parameter_list: empty */ -#line 2035 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; -} -#line 6035 "built/tmp/cppBison.yxx.c" - break; - - case 207: /* function_parameter_list: ELLIPSIS */ -#line 2039 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_includes_ellipsis = true; -} -#line 6044 "built/tmp/cppBison.yxx.c" - break; - - case 208: /* function_parameter_list: function_parameters */ -#line 2044 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[0].u.param_list); -} -#line 6052 "built/tmp/cppBison.yxx.c" - break; - - case 209: /* function_parameter_list: function_parameters ',' ELLIPSIS */ -#line 2048 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[-2].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; -} -#line 6061 "built/tmp/cppBison.yxx.c" - break; - - case 210: /* function_parameter_list: function_parameters ELLIPSIS */ -#line 2053 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[-1].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; -} -#line 6070 "built/tmp/cppBison.yxx.c" - break; - - case 211: /* function_parameters: function_parameter */ -#line 2061 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); -} -#line 6079 "built/tmp/cppBison.yxx.c" - break; - - case 212: /* function_parameters: function_parameters ',' function_parameter */ -#line 2066 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[-2].u.param_list); - (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); -} -#line 6088 "built/tmp/cppBison.yxx.c" - break; - - case 213: /* formal_parameter_list: empty */ -#line 2074 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; -} -#line 6096 "built/tmp/cppBison.yxx.c" - break; - - case 214: /* formal_parameter_list: ELLIPSIS */ -#line 2078 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_includes_ellipsis = true; -} -#line 6105 "built/tmp/cppBison.yxx.c" - break; - - case 215: /* formal_parameter_list: formal_parameters */ -#line 2083 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[0].u.param_list); -} -#line 6113 "built/tmp/cppBison.yxx.c" - break; - - case 216: /* formal_parameter_list: formal_parameters ',' ELLIPSIS */ -#line 2087 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[-2].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; -} -#line 6122 "built/tmp/cppBison.yxx.c" - break; - - case 217: /* formal_parameter_list: formal_parameters ELLIPSIS */ -#line 2092 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[-1].u.param_list); - (yyval.u.param_list)->_includes_ellipsis = true; -} -#line 6131 "built/tmp/cppBison.yxx.c" - break; - - case 218: /* formal_parameters: formal_parameter */ -#line 2100 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; - (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); -} -#line 6140 "built/tmp/cppBison.yxx.c" - break; - - case 219: /* formal_parameters: formal_parameters ',' formal_parameter */ -#line 2105 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = (yyvsp[-2].u.param_list); - (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); -} -#line 6149 "built/tmp/cppBison.yxx.c" - break; - - case 220: /* template_parameter_maybe_initialize: empty */ -#line 2113 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6157 "built/tmp/cppBison.yxx.c" - break; - - case 221: /* template_parameter_maybe_initialize: '=' no_angle_bracket_const_expr */ -#line 2117 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 6165 "built/tmp/cppBison.yxx.c" - break; - - case 222: /* maybe_initialize: empty */ -#line 2124 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6173 "built/tmp/cppBison.yxx.c" - break; - - case 223: /* maybe_initialize: '=' const_expr */ -#line 2128 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 6181 "built/tmp/cppBison.yxx.c" - break; - - case 224: /* maybe_initialize_or_constructor_body: ';' */ -#line 2135 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6189 "built/tmp/cppBison.yxx.c" - break; - - case 225: /* maybe_initialize_or_constructor_body: '{' code '}' */ -#line 2139 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6197 "built/tmp/cppBison.yxx.c" - break; - - case 226: /* maybe_initialize_or_constructor_body: ':' constructor_inits '{' code '}' */ -#line 2143 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6205 "built/tmp/cppBison.yxx.c" - break; - - case 227: /* maybe_initialize_or_constructor_body: '=' KW_DEFAULT ';' */ -#line 2147 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); -} -#line 6213 "built/tmp/cppBison.yxx.c" - break; - - case 228: /* maybe_initialize_or_constructor_body: '=' KW_DELETE ';' */ -#line 2151 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); -} -#line 6221 "built/tmp/cppBison.yxx.c" - break; - - case 229: /* maybe_initialize_or_function_body: ';' */ -#line 2158 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6229 "built/tmp/cppBison.yxx.c" - break; - - case 230: /* maybe_initialize_or_function_body: '{' code '}' */ -#line 2162 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6237 "built/tmp/cppBison.yxx.c" - break; - - case 231: /* maybe_initialize_or_function_body: '=' const_expr ';' */ -#line 2166 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[-1].u.expr); -} -#line 6245 "built/tmp/cppBison.yxx.c" - break; - - case 232: /* maybe_initialize_or_function_body: '=' KW_DEFAULT ';' */ -#line 2170 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); -} -#line 6253 "built/tmp/cppBison.yxx.c" - break; - - case 233: /* maybe_initialize_or_function_body: '=' KW_DELETE ';' */ -#line 2174 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); -} -#line 6261 "built/tmp/cppBison.yxx.c" - break; - - case 234: /* maybe_initialize_or_function_body: '=' '{' structure_init '}' */ -#line 2178 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6269 "built/tmp/cppBison.yxx.c" - break; - - case 238: /* structure_init_body: const_expr */ -#line 2191 "dtool/src/cppparser/cppBison.yxx" -{ -} -#line 6276 "built/tmp/cppBison.yxx.c" - break; - - case 242: /* function_parameter: optional_attributes storage_class type formal_parameter_identifier maybe_initialize */ -#line 2200 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-3].u.integer) & CPPInstance::SC_const) { - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - } - if ((yyvsp[-3].u.integer) & CPPInstance::SC_volatile) { - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_volatile); - } - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-4].attr_list)); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6292 "built/tmp/cppBison.yxx.c" - break; - - case 243: /* function_parameter: optional_attributes storage_class type_pack parameter_pack_identifier maybe_initialize */ -#line 2212 "dtool/src/cppparser/cppBison.yxx" -{ - if ((yyvsp[-3].u.integer) & CPPInstance::SC_const) { - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - } - if ((yyvsp[-3].u.integer) & CPPInstance::SC_volatile) { - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_volatile); - } - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-4].attr_list)); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6308 "built/tmp/cppBison.yxx.c" - break; - - case 244: /* formal_parameter: function_parameter */ -#line 2231 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.instance) = (yyvsp[0].u.instance); -} -#line 6316 "built/tmp/cppBison.yxx.c" - break; - - case 245: /* formal_parameter: formal_const_expr */ -#line 2235 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_parameter)); - (yyval.u.instance) = new CPPInstance(type, "expr"); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6327 "built/tmp/cppBison.yxx.c" - break; - - case 246: /* not_paren_formal_parameter_identifier: empty */ -#line 2245 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); -} -#line 6335 "built/tmp/cppBison.yxx.c" - break; - - case 247: /* not_paren_formal_parameter_identifier: name_no_final optional_attributes */ -#line 2249 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); -} -#line 6343 "built/tmp/cppBison.yxx.c" - break; - - case 248: /* not_paren_formal_parameter_identifier: KW_CONST not_paren_formal_parameter_identifier */ -#line 2253 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} -#line 6352 "built/tmp/cppBison.yxx.c" - break; - - case 249: /* not_paren_formal_parameter_identifier: KW_VOLATILE not_paren_formal_parameter_identifier */ -#line 2258 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} -#line 6361 "built/tmp/cppBison.yxx.c" - break; - - case 250: /* not_paren_formal_parameter_identifier: KW_RESTRICT not_paren_formal_parameter_identifier */ -#line 2263 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_restrict); -} -#line 6370 "built/tmp/cppBison.yxx.c" - break; - - case 251: /* not_paren_formal_parameter_identifier: '*' optional_attributes not_paren_formal_parameter_identifier */ -#line 2268 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); -} -#line 6379 "built/tmp/cppBison.yxx.c" - break; - - case 252: /* not_paren_formal_parameter_identifier: '&' optional_attributes not_paren_formal_parameter_identifier */ -#line 2273 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); -} -#line 6388 "built/tmp/cppBison.yxx.c" - break; - - case 253: /* not_paren_formal_parameter_identifier: ANDAND optional_attributes not_paren_formal_parameter_identifier */ -#line 2278 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); -} -#line 6397 "built/tmp/cppBison.yxx.c" - break; - - case 254: /* not_paren_formal_parameter_identifier: SCOPING '*' optional_attributes not_paren_formal_parameter_identifier */ -#line 2283 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); -} -#line 6406 "built/tmp/cppBison.yxx.c" - break; - - case 255: /* not_paren_formal_parameter_identifier: not_paren_formal_parameter_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2288 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); -} -#line 6415 "built/tmp/cppBison.yxx.c" - break; - - case 256: /* formal_parameter_identifier: empty */ -#line 2296 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); -} -#line 6423 "built/tmp/cppBison.yxx.c" - break; - - case 257: /* formal_parameter_identifier: name_no_final optional_attributes */ -#line 2300 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); -} -#line 6431 "built/tmp/cppBison.yxx.c" - break; - - case 258: /* formal_parameter_identifier: KW_CONST formal_parameter_identifier */ -#line 2304 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} -#line 6440 "built/tmp/cppBison.yxx.c" - break; - - case 259: /* formal_parameter_identifier: KW_VOLATILE formal_parameter_identifier */ -#line 2309 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} -#line 6449 "built/tmp/cppBison.yxx.c" - break; - - case 260: /* formal_parameter_identifier: KW_RESTRICT formal_parameter_identifier */ -#line 2314 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_restrict); -} -#line 6458 "built/tmp/cppBison.yxx.c" - break; - - case 261: /* formal_parameter_identifier: '*' optional_attributes formal_parameter_identifier */ -#line 2319 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); -} -#line 6467 "built/tmp/cppBison.yxx.c" - break; - - case 262: /* formal_parameter_identifier: '&' optional_attributes formal_parameter_identifier */ -#line 2324 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); -} -#line 6476 "built/tmp/cppBison.yxx.c" - break; - - case 263: /* formal_parameter_identifier: ANDAND optional_attributes formal_parameter_identifier */ -#line 2329 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); -} -#line 6485 "built/tmp/cppBison.yxx.c" - break; - - case 264: /* formal_parameter_identifier: SCOPING '*' optional_attributes formal_parameter_identifier */ -#line 2334 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); -} -#line 6494 "built/tmp/cppBison.yxx.c" - break; - - case 265: /* formal_parameter_identifier: formal_parameter_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2339 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); -} -#line 6503 "built/tmp/cppBison.yxx.c" - break; - - case 266: /* formal_parameter_identifier: '(' formal_parameter_identifier ')' '(' function_parameter_list ')' function_post optional_attributes */ -#line 2344 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); -} -#line 6513 "built/tmp/cppBison.yxx.c" - break; - - case 267: /* formal_parameter_identifier: '(' formal_parameter_identifier ')' */ -#line 2350 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); -} -#line 6522 "built/tmp/cppBison.yxx.c" - break; - - case 268: /* parameter_pack_identifier: ELLIPSIS */ -#line 2358 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); - (yyval.u.inst_ident)->_packed = true; -} -#line 6531 "built/tmp/cppBison.yxx.c" - break; - - case 269: /* parameter_pack_identifier: ELLIPSIS name optional_attributes */ -#line 2363 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); - (yyval.u.inst_ident)->_packed = true; -} -#line 6540 "built/tmp/cppBison.yxx.c" - break; - - case 270: /* parameter_pack_identifier: KW_CONST parameter_pack_identifier */ -#line 2368 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} -#line 6549 "built/tmp/cppBison.yxx.c" - break; - - case 271: /* parameter_pack_identifier: KW_VOLATILE parameter_pack_identifier */ -#line 2373 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} -#line 6558 "built/tmp/cppBison.yxx.c" - break; - - case 272: /* parameter_pack_identifier: KW_RESTRICT parameter_pack_identifier */ -#line 2378 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_restrict); -} -#line 6567 "built/tmp/cppBison.yxx.c" - break; - - case 273: /* parameter_pack_identifier: '*' optional_attributes parameter_pack_identifier */ -#line 2383 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); -} -#line 6576 "built/tmp/cppBison.yxx.c" - break; - - case 274: /* parameter_pack_identifier: '&' optional_attributes parameter_pack_identifier */ -#line 2388 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); -} -#line 6585 "built/tmp/cppBison.yxx.c" - break; - - case 275: /* parameter_pack_identifier: ANDAND optional_attributes parameter_pack_identifier */ -#line 2393 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); -} -#line 6594 "built/tmp/cppBison.yxx.c" - break; - - case 276: /* parameter_pack_identifier: SCOPING '*' optional_attributes parameter_pack_identifier */ -#line 2398 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); -} -#line 6603 "built/tmp/cppBison.yxx.c" - break; - - case 277: /* parameter_pack_identifier: parameter_pack_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2403 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); -} -#line 6612 "built/tmp/cppBison.yxx.c" - break; - - case 278: /* parameter_pack_identifier: '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post optional_attributes */ -#line 2408 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); -} -#line 6622 "built/tmp/cppBison.yxx.c" - break; - - case 279: /* parameter_pack_identifier: '(' parameter_pack_identifier ')' */ -#line 2414 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_paren); -} -#line 6631 "built/tmp/cppBison.yxx.c" - break; - - case 280: /* not_paren_empty_instance_identifier: empty */ -#line 2422 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); -} -#line 6639 "built/tmp/cppBison.yxx.c" - break; - - case 281: /* not_paren_empty_instance_identifier: ELLIPSIS */ -#line 2426 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); - (yyval.u.inst_ident)->_packed = true; -} -#line 6648 "built/tmp/cppBison.yxx.c" - break; - - case 282: /* not_paren_empty_instance_identifier: ELLIPSIS name optional_attributes */ -#line 2431 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); - (yyval.u.inst_ident)->_packed = true; -} -#line 6657 "built/tmp/cppBison.yxx.c" - break; - - case 283: /* not_paren_empty_instance_identifier: KW_CONST not_paren_empty_instance_identifier */ -#line 2436 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} -#line 6666 "built/tmp/cppBison.yxx.c" - break; - - case 284: /* not_paren_empty_instance_identifier: KW_VOLATILE not_paren_empty_instance_identifier */ -#line 2441 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} -#line 6675 "built/tmp/cppBison.yxx.c" - break; - - case 285: /* not_paren_empty_instance_identifier: KW_RESTRICT not_paren_empty_instance_identifier */ -#line 2446 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_restrict); -} -#line 6684 "built/tmp/cppBison.yxx.c" - break; - - case 286: /* not_paren_empty_instance_identifier: '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2451 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); -} -#line 6693 "built/tmp/cppBison.yxx.c" - break; - - case 287: /* not_paren_empty_instance_identifier: '&' optional_attributes not_paren_empty_instance_identifier */ -#line 2456 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); -} -#line 6702 "built/tmp/cppBison.yxx.c" - break; - - case 288: /* not_paren_empty_instance_identifier: ANDAND optional_attributes not_paren_empty_instance_identifier */ -#line 2461 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); -} -#line 6711 "built/tmp/cppBison.yxx.c" - break; - - case 289: /* not_paren_empty_instance_identifier: SCOPING '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2466 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); -} -#line 6720 "built/tmp/cppBison.yxx.c" - break; - - case 290: /* not_paren_empty_instance_identifier: not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2471 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); -} -#line 6729 "built/tmp/cppBison.yxx.c" - break; - - case 291: /* empty_instance_identifier: empty */ -#line 2479 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); -} -#line 6737 "built/tmp/cppBison.yxx.c" - break; - - case 292: /* empty_instance_identifier: ELLIPSIS */ -#line 2483 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); - (yyval.u.inst_ident)->_packed = true; -} -#line 6746 "built/tmp/cppBison.yxx.c" - break; - - case 293: /* empty_instance_identifier: ELLIPSIS name optional_attributes */ -#line 2488 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); - (yyval.u.inst_ident)->_packed = true; -} -#line 6755 "built/tmp/cppBison.yxx.c" - break; - - case 294: /* empty_instance_identifier: KW_CONST empty_instance_identifier */ -#line 2493 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_const); -} -#line 6764 "built/tmp/cppBison.yxx.c" - break; - - case 295: /* empty_instance_identifier: KW_VOLATILE empty_instance_identifier */ -#line 2498 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_volatile); -} -#line 6773 "built/tmp/cppBison.yxx.c" - break; - - case 296: /* empty_instance_identifier: KW_RESTRICT empty_instance_identifier */ -#line 2503 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_restrict); -} -#line 6782 "built/tmp/cppBison.yxx.c" - break; - - case 297: /* empty_instance_identifier: '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2508 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); -} -#line 6791 "built/tmp/cppBison.yxx.c" - break; - - case 298: /* empty_instance_identifier: '&' optional_attributes not_paren_empty_instance_identifier */ -#line 2513 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); -} -#line 6800 "built/tmp/cppBison.yxx.c" - break; - - case 299: /* empty_instance_identifier: ANDAND optional_attributes not_paren_empty_instance_identifier */ -#line 2518 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); -} -#line 6809 "built/tmp/cppBison.yxx.c" - break; - - case 300: /* empty_instance_identifier: SCOPING '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2523 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); - (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); -} -#line 6818 "built/tmp/cppBison.yxx.c" - break; - - case 301: /* empty_instance_identifier: not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2528 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); - (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); -} -#line 6827 "built/tmp/cppBison.yxx.c" - break; - - case 302: /* empty_instance_identifier: '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2533 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); -} -#line 6837 "built/tmp/cppBison.yxx.c" - break; - - case 303: /* empty_instance_identifier: '(' '*' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2539 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-7].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-8].attr_list)); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); -} -#line 6848 "built/tmp/cppBison.yxx.c" - break; - - case 304: /* empty_instance_identifier: '(' '&' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2546 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-7].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-8].attr_list)); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); -} -#line 6859 "built/tmp/cppBison.yxx.c" - break; - - case 305: /* empty_instance_identifier: '(' ANDAND optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2553 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.inst_ident) = (yyvsp[-7].u.inst_ident); - (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-8].attr_list)); - (yyval.u.inst_ident)->add_modifier(IIT_paren); - (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); -} -#line 6870 "built/tmp/cppBison.yxx.c" - break; - - case 306: /* type: simple_type */ -#line 2563 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); -} -#line 6878 "built/tmp/cppBison.yxx.c" - break; - - case 307: /* type: TYPENAME_IDENTIFIER */ -#line 2567 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - } - assert((yyval.u.type) != nullptr); -} -#line 6890 "built/tmp/cppBison.yxx.c" - break; - - case 308: /* type: KW_TYPENAME name */ -#line 2575 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); -} -#line 6898 "built/tmp/cppBison.yxx.c" - break; - - case 309: /* type: anonymous_struct */ -#line 2579 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.struct_type)); -} -#line 6906 "built/tmp/cppBison.yxx.c" - break; - - case 310: /* type: named_struct */ -#line 2583 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.struct_type)); -} -#line 6914 "built/tmp/cppBison.yxx.c" - break; - - case 311: /* type: enum */ -#line 2587 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.enum_type)); -} -#line 6922 "built/tmp/cppBison.yxx.c" - break; - - case 312: /* type: struct_keyword optional_attributes name */ -#line 2591 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.type) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.type) = et; - } -} -#line 6942 "built/tmp/cppBison.yxx.c" - break; - - case 313: /* type: enum_keyword optional_attributes name_no_final ':' enum_element_type */ -#line 2607 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[-2].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.type) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-4].u.extension_enum), (yyvsp[-2].u.identifier), current_scope, (yylsp[-4]).file, (yyvsp[-3].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[-2].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.type) = et; - } -} -#line 6962 "built/tmp/cppBison.yxx.c" - break; - - case 314: /* type: KW_DECLTYPE '(' const_expr ')' */ -#line 2623 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[-1].u.expr)->determine_type(); - if ((yyval.u.type) == nullptr) { - stringstream str; - str << *(yyvsp[-1].u.expr); - yyerror("could not determine type of " + str.str(), (yylsp[-1])); - } -} -#line 6975 "built/tmp/cppBison.yxx.c" - break; - - case 315: /* type: KW_DECLTYPE '(' KW_AUTO ')' */ -#line 2632 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} -#line 6983 "built/tmp/cppBison.yxx.c" - break; - - case 316: /* type: KW_UNDERLYING_TYPE '(' full_type ')' */ -#line 2636 "dtool/src/cppparser/cppBison.yxx" -{ - CPPEnumType *enum_type = (yyvsp[-1].u.type)->as_enum_type(); - if (enum_type == nullptr) { - yyerror("an enumeration type is required", (yylsp[-1])); - (yyval.u.type) = (yyvsp[-1].u.type); - } else { - (yyval.u.type) = enum_type->get_underlying_type(); - } -} -#line 6997 "built/tmp/cppBison.yxx.c" - break; - - case 317: /* type: KW_AUTO */ -#line 2646 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} -#line 7005 "built/tmp/cppBison.yxx.c" - break; - - case 318: /* type: KW_BUILTIN_VA_LIST */ -#line 2650 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); -} -#line 7013 "built/tmp/cppBison.yxx.c" - break; - - case 319: /* type_pack: TYPEPACK_IDENTIFIER */ -#line 2657 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - } - assert((yyval.u.type) != nullptr); -} -#line 7025 "built/tmp/cppBison.yxx.c" - break; - - case 320: /* type_decl: simple_type */ -#line 2668 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type((yyvsp[0].u.simple_type)); -} -#line 7033 "built/tmp/cppBison.yxx.c" - break; - - case 321: /* type_decl: TYPENAME_IDENTIFIER */ -#line 2672 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.decl) == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - } - assert((yyval.u.decl) != nullptr); -} -#line 7045 "built/tmp/cppBison.yxx.c" - break; - - case 322: /* type_decl: KW_TYPENAME name */ -#line 2680 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); -} -#line 7053 "built/tmp/cppBison.yxx.c" - break; - - case 323: /* type_decl: anonymous_struct */ -#line 2684 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type((yyvsp[0].u.struct_type)); -} -#line 7061 "built/tmp/cppBison.yxx.c" - break; - - case 324: /* type_decl: named_struct */ -#line 2688 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[0].u.struct_type))); -} -#line 7069 "built/tmp/cppBison.yxx.c" - break; - - case 325: /* type_decl: enum */ -#line 2692 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[0].u.enum_type))); -} -#line 7077 "built/tmp/cppBison.yxx.c" - break; - - case 326: /* type_decl: struct_keyword optional_attributes name */ -#line 2696 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.decl) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.decl) = et; - } -} -#line 7097 "built/tmp/cppBison.yxx.c" - break; - - case 327: /* type_decl: enum_keyword optional_attributes name_no_final ':' enum_element_type */ -#line 2712 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[-2].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.decl) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-4].u.extension_enum), (yyvsp[-2].u.identifier), current_scope, (yylsp[-4]).file, (yyvsp[-3].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[-2].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.decl) = et; - } -} -#line 7117 "built/tmp/cppBison.yxx.c" - break; - - case 328: /* type_decl: enum_keyword optional_attributes name */ -#line 2728 "dtool/src/cppparser/cppBison.yxx" -{ - yywarning(string("C++ does not permit forward declaration of untyped enum ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); - - CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.decl) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.decl) = et; - } -} -#line 7139 "built/tmp/cppBison.yxx.c" - break; - - case 329: /* type_decl: KW_DECLTYPE '(' const_expr ')' */ -#line 2746 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = (yyvsp[-1].u.expr)->determine_type(); - if ((yyval.u.decl) == nullptr) { - stringstream str; - str << *(yyvsp[-1].u.expr); - yyerror("could not determine type of " + str.str(), (yylsp[-1])); - } -} -#line 7152 "built/tmp/cppBison.yxx.c" - break; - - case 330: /* type_decl: KW_DECLTYPE '(' KW_AUTO ')' */ -#line 2755 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} -#line 7160 "built/tmp/cppBison.yxx.c" - break; - - case 331: /* type_decl: KW_UNDERLYING_TYPE '(' full_type ')' */ -#line 2759 "dtool/src/cppparser/cppBison.yxx" -{ - CPPEnumType *enum_type = (yyvsp[-1].u.type)->as_enum_type(); - if (enum_type == nullptr) { - yyerror("an enumeration type is required", (yylsp[-1])); - (yyval.u.decl) = (yyvsp[-1].u.type); - } else { - (yyval.u.decl) = enum_type->get_underlying_type(); - } -} -#line 7174 "built/tmp/cppBison.yxx.c" - break; - - case 332: /* type_decl: KW_AUTO */ -#line 2769 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} -#line 7182 "built/tmp/cppBison.yxx.c" - break; - - case 333: /* type_decl: KW_BUILTIN_VA_LIST */ -#line 2773 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); -} -#line 7190 "built/tmp/cppBison.yxx.c" - break; - - case 334: /* predefined_type: simple_type */ -#line 2780 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); -} -#line 7198 "built/tmp/cppBison.yxx.c" - break; - - case 335: /* predefined_type: TYPENAME_IDENTIFIER */ -#line 2784 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if ((yyval.u.type) == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); - } - assert((yyval.u.type) != nullptr); -} -#line 7210 "built/tmp/cppBison.yxx.c" - break; - - case 336: /* predefined_type: KW_TYPENAME name */ -#line 2792 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); -} -#line 7218 "built/tmp/cppBison.yxx.c" - break; - - case 337: /* predefined_type: struct_keyword optional_attributes name */ -#line 2796 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.type) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.type) = et; - } -} -#line 7238 "built/tmp/cppBison.yxx.c" - break; - - case 338: /* predefined_type: enum_keyword optional_attributes name */ -#line 2812 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - (yyval.u.type) = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list))) - ->as_extension_type(); - CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - (yyval.u.type) = et; - } -} -#line 7258 "built/tmp/cppBison.yxx.c" - break; - - case 339: /* predefined_type: KW_DECLTYPE '(' const_expr ')' */ -#line 2828 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[-1].u.expr)->determine_type(); - if ((yyval.u.type) == nullptr) { - stringstream str; - str << *(yyvsp[-1].u.expr); - yyerror("could not determine type of " + str.str(), (yylsp[-1])); - } -} -#line 7271 "built/tmp/cppBison.yxx.c" - break; - - case 340: /* predefined_type: KW_UNDERLYING_TYPE '(' full_type ')' */ -#line 2837 "dtool/src/cppparser/cppBison.yxx" -{ - CPPEnumType *enum_type = (yyvsp[-1].u.type)->as_enum_type(); - if (enum_type == nullptr) { - yyerror("an enumeration type is required", (yylsp[-1])); - (yyval.u.type) = (yyvsp[-1].u.type); - } else { - (yyval.u.type) = enum_type->get_underlying_type(); - } -} -#line 7285 "built/tmp/cppBison.yxx.c" - break; - - case 341: /* predefined_type: KW_AUTO */ -#line 2847 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} -#line 7293 "built/tmp/cppBison.yxx.c" - break; - - case 342: /* predefined_type: KW_BUILTIN_VA_LIST */ -#line 2851 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); -} -#line 7301 "built/tmp/cppBison.yxx.c" - break; - - case 343: /* var_type_decl: type_decl */ -#line 2858 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.decl) = (yyvsp[0].u.decl); -} -#line 7309 "built/tmp/cppBison.yxx.c" - break; - - case 344: /* var_type_decl: IDENTIFIER */ -#line 2862 "dtool/src/cppparser/cppBison.yxx" -{ - yyerror(string("unknown type '") + (yyvsp[0].u.identifier)->get_fully_scoped_name() + "'", (yylsp[0])); - - (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); -} -#line 7319 "built/tmp/cppBison.yxx.c" - break; - - case 345: /* full_type: type empty_instance_identifier */ -#line 2870 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); -} -#line 7327 "built/tmp/cppBison.yxx.c" - break; - - case 346: /* full_type: KW_CONST type empty_instance_identifier */ -#line 2874 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); -} -#line 7336 "built/tmp/cppBison.yxx.c" - break; - - case 347: /* full_type: type_pack empty_instance_identifier */ -#line 2879 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); -} -#line 7344 "built/tmp/cppBison.yxx.c" - break; - - case 348: /* full_type: KW_CONST type_pack empty_instance_identifier */ -#line 2883 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); -} -#line 7353 "built/tmp/cppBison.yxx.c" - break; - - case 349: /* $@17: %empty */ -#line 2891 "dtool/src/cppparser/cppBison.yxx" -{ - CPPVisibility starting_vis = - ((yyvsp[-2].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; - - CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"), - starting_vis); - CPPStructType *st = new CPPStructType((yyvsp[-2].u.extension_enum), nullptr, current_scope, - new_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list)); - new_scope->set_struct_type(st); - - push_scope(new_scope); - push_struct(st); -} -#line 7371 "built/tmp/cppBison.yxx.c" - break; - - case 350: /* anonymous_struct: struct_keyword optional_attributes '{' $@17 cpp '}' */ -#line 2905 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.struct_type) = current_struct; - current_struct->_incomplete = false; - pop_struct(); - pop_scope(); -} -#line 7382 "built/tmp/cppBison.yxx.c" - break; - - case 351: /* $@18: %empty */ -#line 2915 "dtool/src/cppparser/cppBison.yxx" -{ - CPPVisibility starting_vis = - ((yyvsp[-2].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; - - CPPScope *scope = (yyvsp[0].u.identifier)->get_scope(current_scope, global_scope, current_lexer); - if (scope == nullptr) { - scope = current_scope; - } - CPPScope *new_scope = new CPPScope(scope, (yyvsp[0].u.identifier)->_names.back(), - starting_vis); - - CPPStructType *st = new CPPStructType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, - new_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list)); - new_scope->set_struct_type(st); - current_scope->define_extension_type(st); - - push_scope(new_scope); - push_struct(st); -} -#line 7406 "built/tmp/cppBison.yxx.c" - break; - - case 352: /* named_struct: struct_keyword optional_attributes name_no_final $@18 maybe_final maybe_class_derivation '{' cpp '}' */ -#line 2935 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.struct_type) = current_struct; - current_struct->_incomplete = false; - pop_struct(); - pop_scope(); -} -#line 7417 "built/tmp/cppBison.yxx.c" - break; - - case 354: /* maybe_final: KW_FINAL */ -#line 2946 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->_final = true; -} -#line 7425 "built/tmp/cppBison.yxx.c" - break; - - case 359: /* base_specification: class_derivation_name */ -#line 2963 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_unknown, false); -} -#line 7433 "built/tmp/cppBison.yxx.c" - break; - - case 360: /* base_specification: KW_PUBLIC class_derivation_name */ -#line 2967 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_public, false); -} -#line 7441 "built/tmp/cppBison.yxx.c" - break; - - case 361: /* base_specification: KW_PROTECTED class_derivation_name */ -#line 2971 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_protected, false); -} -#line 7449 "built/tmp/cppBison.yxx.c" - break; - - case 362: /* base_specification: KW_PRIVATE class_derivation_name */ -#line 2975 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_private, false); -} -#line 7457 "built/tmp/cppBison.yxx.c" - break; - - case 363: /* base_specification: KW_VIRTUAL KW_PUBLIC class_derivation_name */ -#line 2979 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_public, true); -} -#line 7465 "built/tmp/cppBison.yxx.c" - break; - - case 364: /* base_specification: KW_VIRTUAL KW_PROTECTED class_derivation_name */ -#line 2983 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_protected, true); -} -#line 7473 "built/tmp/cppBison.yxx.c" - break; - - case 365: /* base_specification: KW_VIRTUAL KW_PRIVATE class_derivation_name */ -#line 2987 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_private, true); -} -#line 7481 "built/tmp/cppBison.yxx.c" - break; - - case 366: /* base_specification: KW_PUBLIC KW_VIRTUAL class_derivation_name */ -#line 2991 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_public, true); -} -#line 7489 "built/tmp/cppBison.yxx.c" - break; - - case 367: /* base_specification: KW_PROTECTED KW_VIRTUAL class_derivation_name */ -#line 2995 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_protected, true); -} -#line 7497 "built/tmp/cppBison.yxx.c" - break; - - case 368: /* base_specification: KW_PRIVATE KW_VIRTUAL class_derivation_name */ -#line 2999 "dtool/src/cppparser/cppBison.yxx" -{ - current_struct->append_derivation((yyvsp[0].u.type), V_private, true); -} -#line 7505 "built/tmp/cppBison.yxx.c" - break; - - case 369: /* $@19: %empty */ -#line 3006 "dtool/src/cppparser/cppBison.yxx" -{ - if (current_enum->_scope != nullptr) { - push_scope(current_enum->_scope); - } -} -#line 7515 "built/tmp/cppBison.yxx.c" - break; - - case 370: /* enum: enum_decl $@19 '{' enum_body '}' */ -#line 3012 "dtool/src/cppparser/cppBison.yxx" -{ - if (current_enum->_scope != nullptr) { - pop_scope(); - } - (yyval.u.enum_type) = current_enum; - current_enum = nullptr; -} -#line 7527 "built/tmp/cppBison.yxx.c" - break; - - case 371: /* enum_decl: enum_keyword optional_attributes ':' enum_element_type */ -#line 3023 "dtool/src/cppparser/cppBison.yxx" -{ - current_enum = new CPPEnumType((yyvsp[-3].u.extension_enum), nullptr, (yyvsp[0].u.type), current_scope, nullptr, (yylsp[-3]).file, (yyvsp[-2].attr_list)); -} -#line 7535 "built/tmp/cppBison.yxx.c" - break; - - case 372: /* enum_decl: enum_keyword optional_attributes */ -#line 3027 "dtool/src/cppparser/cppBison.yxx" -{ - current_enum = new CPPEnumType((yyvsp[-1].u.extension_enum), nullptr, current_scope, nullptr, (yylsp[-1]).file, (yyvsp[0].attr_list)); -} -#line 7543 "built/tmp/cppBison.yxx.c" - break; - - case 373: /* enum_decl: enum_keyword optional_attributes name_no_final ':' enum_element_type */ -#line 3031 "dtool/src/cppparser/cppBison.yxx" -{ - CPPScope *new_scope = new CPPScope(current_scope, (yyvsp[-2].u.identifier)->_names.back(), V_public); - current_enum = new CPPEnumType((yyvsp[-4].u.extension_enum), (yyvsp[-2].u.identifier), (yyvsp[0].u.type), current_scope, new_scope, (yylsp[-4]).file, (yyvsp[-3].attr_list)); -} -#line 7552 "built/tmp/cppBison.yxx.c" - break; - - case 374: /* enum_decl: enum_keyword optional_attributes name_no_final */ -#line 3036 "dtool/src/cppparser/cppBison.yxx" -{ - CPPScope *new_scope = new CPPScope(current_scope, (yyvsp[0].u.identifier)->_names.back(), V_public); - current_enum = new CPPEnumType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, new_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list)); -} -#line 7561 "built/tmp/cppBison.yxx.c" - break; - - case 375: /* enum_element_type: simple_int_type */ -#line 3044 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); -} -#line 7569 "built/tmp/cppBison.yxx.c" - break; - - case 376: /* enum_element_type: TYPENAME_IDENTIFIER */ -#line 3048 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); -} -#line 7577 "built/tmp/cppBison.yxx.c" - break; - - case 378: /* enum_body_trailing_comma: enum_body_trailing_comma name optional_attributes ',' */ -#line 3056 "dtool/src/cppparser/cppBison.yxx" -{ - assert(current_enum != nullptr); - current_enum->add_element((yyvsp[-2].u.identifier)->get_simple_name(), nullptr, current_lexer, (yylsp[-2]), (yyvsp[-1].attr_list)); -} -#line 7586 "built/tmp/cppBison.yxx.c" - break; - - case 379: /* enum_body_trailing_comma: enum_body_trailing_comma name optional_attributes '=' const_expr ',' */ -#line 3061 "dtool/src/cppparser/cppBison.yxx" -{ - assert(current_enum != nullptr); - current_enum->add_element((yyvsp[-4].u.identifier)->get_simple_name(), (yyvsp[-1].u.expr), current_lexer, (yylsp[-4]), (yyvsp[-3].attr_list)); -} -#line 7595 "built/tmp/cppBison.yxx.c" - break; - - case 381: /* enum_body: enum_body_trailing_comma name optional_attributes */ -#line 3069 "dtool/src/cppparser/cppBison.yxx" -{ - assert(current_enum != nullptr); - current_enum->add_element((yyvsp[-1].u.identifier)->get_simple_name(), nullptr, current_lexer, (yylsp[-1]), (yyvsp[0].attr_list)); -} -#line 7604 "built/tmp/cppBison.yxx.c" - break; - - case 382: /* enum_body: enum_body_trailing_comma name optional_attributes '=' const_expr */ -#line 3074 "dtool/src/cppparser/cppBison.yxx" -{ - assert(current_enum != nullptr); - current_enum->add_element((yyvsp[-3].u.identifier)->get_simple_name(), (yyvsp[0].u.expr), current_lexer, (yylsp[-3]), (yyvsp[-2].attr_list)); -} -#line 7613 "built/tmp/cppBison.yxx.c" - break; - - case 383: /* enum_keyword: KW_ENUM */ -#line 3082 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.extension_enum) = CPPExtensionType::T_enum; -} -#line 7621 "built/tmp/cppBison.yxx.c" - break; - - case 384: /* enum_keyword: KW_ENUM KW_CLASS */ -#line 3086 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.extension_enum) = CPPExtensionType::T_enum_class; -} -#line 7629 "built/tmp/cppBison.yxx.c" - break; - - case 385: /* enum_keyword: KW_ENUM KW_STRUCT */ -#line 3090 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.extension_enum) = CPPExtensionType::T_enum_struct; -} -#line 7637 "built/tmp/cppBison.yxx.c" - break; - - case 386: /* struct_keyword: KW_CLASS */ -#line 3097 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.extension_enum) = CPPExtensionType::T_class; -} -#line 7645 "built/tmp/cppBison.yxx.c" - break; - - case 387: /* struct_keyword: KW_STRUCT */ -#line 3101 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.extension_enum) = CPPExtensionType::T_struct; -} -#line 7653 "built/tmp/cppBison.yxx.c" - break; - - case 388: /* struct_keyword: KW_UNION */ -#line 3105 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.extension_enum) = CPPExtensionType::T_union; -} -#line 7661 "built/tmp/cppBison.yxx.c" - break; - - case 389: /* $@20: %empty */ -#line 3112 "dtool/src/cppparser/cppBison.yxx" -{ - CPPScope *scope = (yyvsp[-1].u.identifier)->find_scope(current_scope, global_scope, current_lexer); - if (scope == nullptr) { - // This must be a new namespace declaration. - CPPScope *parent_scope = - (yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope, current_lexer); - if (parent_scope == nullptr) { - parent_scope = current_scope; - } - scope = new CPPScope(parent_scope, (yyvsp[-1].u.identifier)->_names.back(), V_public); - } - - CPPNamespace *nspace = new CPPNamespace((yyvsp[-1].u.identifier), scope, (yylsp[-3]).file, (yyvsp[-2].attr_list)); - current_scope->add_declaration(nspace, global_scope, current_lexer, (yylsp[-3])); - current_scope->define_namespace(nspace); - push_scope(scope); -} -#line 7683 "built/tmp/cppBison.yxx.c" - break; - - case 390: /* namespace_declaration: KW_NAMESPACE optional_attributes name '{' $@20 cpp '}' */ -#line 3130 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); -} -#line 7691 "built/tmp/cppBison.yxx.c" - break; - - case 391: /* $@21: %empty */ -#line 3134 "dtool/src/cppparser/cppBison.yxx" -{ - CPPScope *scope = (yyvsp[-1].u.identifier)->find_scope(current_scope, global_scope, current_lexer); - if (scope == nullptr) { - // This must be a new namespace declaration. - CPPScope *parent_scope = - (yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope, current_lexer); - if (parent_scope == nullptr) { - parent_scope = current_scope; - } - scope = new CPPScope(parent_scope, (yyvsp[-1].u.identifier)->_names.back(), V_public); - } - - CPPNamespace *nspace = new CPPNamespace((yyvsp[-1].u.identifier), scope, (yylsp[-2]).file); - nspace->_is_inline = true; - current_scope->add_declaration(nspace, global_scope, current_lexer, (yylsp[-2])); - current_scope->define_namespace(nspace); - push_scope(scope); -} -#line 7714 "built/tmp/cppBison.yxx.c" - break; - - case 392: /* namespace_declaration: KW_INLINE KW_NAMESPACE name '{' $@21 cpp '}' */ -#line 3153 "dtool/src/cppparser/cppBison.yxx" -{ - pop_scope(); -} -#line 7722 "built/tmp/cppBison.yxx.c" - break; - - case 395: /* using_declaration: KW_USING name ';' */ -#line 3162 "dtool/src/cppparser/cppBison.yxx" -{ - CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), false, (yylsp[-2]).file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-2])); - current_scope->add_using(using_decl, global_scope, current_lexer); -} -#line 7732 "built/tmp/cppBison.yxx.c" - break; - - case 396: /* using_declaration: KW_USING name optional_attributes '=' full_type ';' */ -#line 3168 "dtool/src/cppparser/cppBison.yxx" -{ - // This is really just an alternative way to declare a typedef. - CPPTypedefType *typedef_type = new CPPTypedefType((yyvsp[-1].u.type), (yyvsp[-4].u.identifier), current_scope, (yyvsp[-3].attr_list)); - typedef_type->_using = true; - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-5])); -} -#line 7743 "built/tmp/cppBison.yxx.c" - break; - - case 397: /* using_declaration: KW_USING KW_NAMESPACE name ';' */ -#line 3175 "dtool/src/cppparser/cppBison.yxx" -{ - CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), true, (yylsp[-3]).file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-3])); - current_scope->add_using(using_decl, global_scope, current_lexer); -} -#line 7753 "built/tmp/cppBison.yxx.c" - break; - - case 398: /* using_declaration: KW_USING KW_ENUM name ';' */ -#line 3181 "dtool/src/cppparser/cppBison.yxx" -{ - CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), false, (yylsp[-3]).file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-3])); - current_scope->add_using(using_decl, global_scope, current_lexer); -} -#line 7763 "built/tmp/cppBison.yxx.c" - break; - - case 402: /* simple_int_type: KW_BOOL */ -#line 3196 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_bool); -} -#line 7771 "built/tmp/cppBison.yxx.c" - break; - - case 403: /* simple_int_type: KW_CHAR */ -#line 3200 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char); -} -#line 7779 "built/tmp/cppBison.yxx.c" - break; - - case 404: /* simple_int_type: KW_WCHAR_T */ -#line 3204 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_wchar_t); -} -#line 7787 "built/tmp/cppBison.yxx.c" - break; - - case 405: /* simple_int_type: KW_CHAR8_T */ -#line 3208 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char8_t); -} -#line 7795 "built/tmp/cppBison.yxx.c" - break; - - case 406: /* simple_int_type: KW_CHAR16_T */ -#line 3212 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char16_t); -} -#line 7803 "built/tmp/cppBison.yxx.c" - break; - - case 407: /* simple_int_type: KW_CHAR32_T */ -#line 3216 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char32_t); -} -#line 7811 "built/tmp/cppBison.yxx.c" - break; - - case 408: /* simple_int_type: KW_SHORT */ -#line 3220 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_short); -} -#line 7820 "built/tmp/cppBison.yxx.c" - break; - - case 409: /* simple_int_type: KW_LONG */ -#line 3225 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_long); -} -#line 7829 "built/tmp/cppBison.yxx.c" - break; - - case 410: /* simple_int_type: KW_UNSIGNED */ -#line 3230 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_unsigned); -} -#line 7838 "built/tmp/cppBison.yxx.c" - break; - - case 411: /* simple_int_type: KW_SIGNED */ -#line 3235 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_signed); -} -#line 7847 "built/tmp/cppBison.yxx.c" - break; - - case 412: /* simple_int_type: KW_INT */ -#line 3240 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int); -} -#line 7855 "built/tmp/cppBison.yxx.c" - break; - - case 413: /* simple_int_type: KW_SHORT simple_int_type */ -#line 3244 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = (yyvsp[0].u.simple_type); - (yyval.u.simple_type)->_flags |= CPPSimpleType::F_short; -} -#line 7864 "built/tmp/cppBison.yxx.c" - break; - - case 414: /* simple_int_type: KW_LONG simple_int_type */ -#line 3249 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = (yyvsp[0].u.simple_type); - if ((yyval.u.simple_type)->_flags & CPPSimpleType::F_long) { - (yyval.u.simple_type)->_flags |= CPPSimpleType::F_longlong; - } else { - (yyval.u.simple_type)->_flags |= CPPSimpleType::F_long; - } -} -#line 7877 "built/tmp/cppBison.yxx.c" - break; - - case 415: /* simple_int_type: KW_UNSIGNED simple_int_type */ -#line 3258 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = (yyvsp[0].u.simple_type); - (yyval.u.simple_type)->_flags |= CPPSimpleType::F_unsigned; -} -#line 7886 "built/tmp/cppBison.yxx.c" - break; - - case 416: /* simple_int_type: KW_SIGNED simple_int_type */ -#line 3263 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = (yyvsp[0].u.simple_type); - (yyval.u.simple_type)->_flags |= CPPSimpleType::F_signed; -} -#line 7895 "built/tmp/cppBison.yxx.c" - break; - - case 417: /* simple_float_type: KW_FLOAT */ -#line 3271 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_float); -} -#line 7903 "built/tmp/cppBison.yxx.c" - break; - - case 418: /* simple_float_type: KW_DOUBLE */ -#line 3275 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_double); -} -#line 7911 "built/tmp/cppBison.yxx.c" - break; - - case 419: /* simple_float_type: KW_LONG KW_DOUBLE */ -#line 3279 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_double, - CPPSimpleType::F_long); -} -#line 7920 "built/tmp/cppBison.yxx.c" - break; - - case 420: /* simple_void_type: KW_VOID */ -#line 3287 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_void); -} -#line 7928 "built/tmp/cppBison.yxx.c" - break; - - case 421: /* $@22: %empty */ -#line 3296 "dtool/src/cppparser/cppBison.yxx" -{ - current_lexer->_resolve_identifiers = false; -} -#line 7936 "built/tmp/cppBison.yxx.c" - break; - - case 422: /* code: $@22 code_block */ -#line 3300 "dtool/src/cppparser/cppBison.yxx" -{ - current_lexer->_resolve_identifiers = true; -} -#line 7944 "built/tmp/cppBison.yxx.c" - break; - - case 539: /* element: KW_WHILE */ -#line 3345 "dtool/src/cppparser/cppBison.yxx" -{ -} -#line 7951 "built/tmp/cppBison.yxx.c" - break; - - case 563: /* optional_const_expr: empty */ -#line 3354 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 7959 "built/tmp/cppBison.yxx.c" - break; - - case 564: /* optional_const_expr: const_expr */ -#line 3358 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 7967 "built/tmp/cppBison.yxx.c" - break; - - case 565: /* optional_const_expr_comma: empty */ -#line 3365 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 7975 "built/tmp/cppBison.yxx.c" - break; - - case 566: /* optional_const_expr_comma: const_expr_comma */ -#line 3369 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 7983 "built/tmp/cppBison.yxx.c" - break; - - case 567: /* const_expr_comma: const_expr */ -#line 3376 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 7991 "built/tmp/cppBison.yxx.c" - break; - - case 568: /* const_expr_comma: const_expr_comma ',' const_expr */ -#line 3380 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(',', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 7999 "built/tmp/cppBison.yxx.c" - break; - - case 569: /* no_angle_bracket_const_expr: const_operand */ -#line 3387 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 8007 "built/tmp/cppBison.yxx.c" - break; - - case 570: /* no_angle_bracket_const_expr: '(' full_type ')' no_angle_bracket_const_expr */ -#line 3391 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); -} -#line 8015 "built/tmp/cppBison.yxx.c" - break; - - case 571: /* no_angle_bracket_const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3395 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); -} -#line 8023 "built/tmp/cppBison.yxx.c" - break; - - case 572: /* no_angle_bracket_const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3399 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); -} -#line 8031 "built/tmp/cppBison.yxx.c" - break; - - case 573: /* no_angle_bracket_const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3403 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); -} -#line 8039 "built/tmp/cppBison.yxx.c" - break; - - case 574: /* no_angle_bracket_const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3407 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); -} -#line 8047 "built/tmp/cppBison.yxx.c" - break; - - case 575: /* no_angle_bracket_const_expr: KW_SIZEOF '(' full_type ')' */ -#line 3411 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); -} -#line 8055 "built/tmp/cppBison.yxx.c" - break; - - case 576: /* no_angle_bracket_const_expr: KW_SIZEOF no_angle_bracket_const_expr */ -#line 3415 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[0].u.expr))); -} -#line 8063 "built/tmp/cppBison.yxx.c" - break; - - case 577: /* no_angle_bracket_const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ -#line 3419 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_ellipsis_func((yyvsp[-1].u.identifier))); -} -#line 8071 "built/tmp/cppBison.yxx.c" - break; - - case 578: /* no_angle_bracket_const_expr: KW_ALIGNOF '(' full_type ')' */ -#line 3423 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); -} -#line 8079 "built/tmp/cppBison.yxx.c" - break; - - case 579: /* no_angle_bracket_const_expr: '!' no_angle_bracket_const_expr */ -#line 3427 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); -} -#line 8087 "built/tmp/cppBison.yxx.c" - break; - - case 580: /* no_angle_bracket_const_expr: '~' no_angle_bracket_const_expr */ -#line 3431 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); -} -#line 8095 "built/tmp/cppBison.yxx.c" - break; - - case 581: /* no_angle_bracket_const_expr: '-' no_angle_bracket_const_expr */ -#line 3435 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); -} -#line 8103 "built/tmp/cppBison.yxx.c" - break; - - case 582: /* no_angle_bracket_const_expr: '+' no_angle_bracket_const_expr */ -#line 3439 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); -} -#line 8111 "built/tmp/cppBison.yxx.c" - break; - - case 583: /* no_angle_bracket_const_expr: '*' no_angle_bracket_const_expr */ -#line 3443 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[0].u.expr)); -} -#line 8119 "built/tmp/cppBison.yxx.c" - break; - - case 584: /* no_angle_bracket_const_expr: '&' no_angle_bracket_const_expr */ -#line 3447 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); -} -#line 8127 "built/tmp/cppBison.yxx.c" - break; - - case 585: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '*' no_angle_bracket_const_expr */ -#line 3451 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8135 "built/tmp/cppBison.yxx.c" - break; - - case 586: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '/' no_angle_bracket_const_expr */ -#line 3455 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8143 "built/tmp/cppBison.yxx.c" - break; - - case 587: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '%' no_angle_bracket_const_expr */ -#line 3459 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8151 "built/tmp/cppBison.yxx.c" - break; - - case 588: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '+' no_angle_bracket_const_expr */ -#line 3463 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8159 "built/tmp/cppBison.yxx.c" - break; - - case 589: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '-' no_angle_bracket_const_expr */ -#line 3467 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8167 "built/tmp/cppBison.yxx.c" - break; - - case 590: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '|' no_angle_bracket_const_expr */ -#line 3471 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8175 "built/tmp/cppBison.yxx.c" - break; - - case 591: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '^' no_angle_bracket_const_expr */ -#line 3475 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8183 "built/tmp/cppBison.yxx.c" - break; - - case 592: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '&' no_angle_bracket_const_expr */ -#line 3479 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8191 "built/tmp/cppBison.yxx.c" - break; - - case 593: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr OROR no_angle_bracket_const_expr */ -#line 3483 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8199 "built/tmp/cppBison.yxx.c" - break; - - case 594: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr ANDAND no_angle_bracket_const_expr */ -#line 3487 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8207 "built/tmp/cppBison.yxx.c" - break; - - case 595: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr EQCOMPARE no_angle_bracket_const_expr */ -#line 3491 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8215 "built/tmp/cppBison.yxx.c" - break; - - case 596: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr NECOMPARE no_angle_bracket_const_expr */ -#line 3495 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8223 "built/tmp/cppBison.yxx.c" - break; - - case 597: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr LECOMPARE no_angle_bracket_const_expr */ -#line 3499 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8231 "built/tmp/cppBison.yxx.c" - break; - - case 598: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr GECOMPARE no_angle_bracket_const_expr */ -#line 3503 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8239 "built/tmp/cppBison.yxx.c" - break; - - case 599: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr SPACESHIP no_angle_bracket_const_expr */ -#line 3507 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(SPACESHIP, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8247 "built/tmp/cppBison.yxx.c" - break; - - case 600: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr LSHIFT no_angle_bracket_const_expr */ -#line 3511 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8255 "built/tmp/cppBison.yxx.c" - break; - - case 601: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr RSHIFT no_angle_bracket_const_expr */ -#line 3515 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8263 "built/tmp/cppBison.yxx.c" - break; - - case 602: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '?' no_angle_bracket_const_expr ':' no_angle_bracket_const_expr */ -#line 3519 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8271 "built/tmp/cppBison.yxx.c" - break; - - case 603: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '[' const_expr ']' */ -#line 3523 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); -} -#line 8279 "built/tmp/cppBison.yxx.c" - break; - - case 604: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '(' const_expr_comma ')' */ -#line 3527 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); -} -#line 8287 "built/tmp/cppBison.yxx.c" - break; - - case 605: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '(' ')' */ -#line 3531 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); -} -#line 8295 "built/tmp/cppBison.yxx.c" - break; - - case 606: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '.' name */ -#line 3535 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer)); -} -#line 8303 "built/tmp/cppBison.yxx.c" - break; - - case 607: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr */ -#line 3539 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8311 "built/tmp/cppBison.yxx.c" - break; - - case 608: /* no_angle_bracket_const_expr: '(' const_expr_comma ')' */ -#line 3543 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[-1].u.expr); -} -#line 8319 "built/tmp/cppBison.yxx.c" - break; - - case 609: /* const_expr: const_operand */ -#line 3551 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 8327 "built/tmp/cppBison.yxx.c" - break; - - case 610: /* const_expr: '(' full_type ')' const_expr */ -#line 3555 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); -} -#line 8335 "built/tmp/cppBison.yxx.c" - break; - - case 611: /* const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3559 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); -} -#line 8343 "built/tmp/cppBison.yxx.c" - break; - - case 612: /* const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3563 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); -} -#line 8351 "built/tmp/cppBison.yxx.c" - break; - - case 613: /* const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3567 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); -} -#line 8359 "built/tmp/cppBison.yxx.c" - break; - - case 614: /* const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3571 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); -} -#line 8367 "built/tmp/cppBison.yxx.c" - break; - - case 615: /* const_expr: TYPENAME_IDENTIFIER '(' optional_const_expr_comma ')' */ -#line 3575 "dtool/src/cppparser/cppBison.yxx" -{ - // A constructor call. - CPPType *type = (yyvsp[-3].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[-3].u.identifier)->get_fully_scoped_name(), (yylsp[-3])); - } - assert(type != nullptr); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8381 "built/tmp/cppBison.yxx.c" - break; - - case 616: /* const_expr: TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}' */ -#line 3585 "dtool/src/cppparser/cppBison.yxx" -{ - // Aggregate initialization. - CPPType *type = (yyvsp[-3].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + (yyvsp[-3].u.identifier)->get_fully_scoped_name(), (yylsp[-3])); - } - assert(type != nullptr); - (yyval.u.expr) = new CPPExpression(CPPExpression::aggregate_init_op(type, (yyvsp[-1].u.expr))); -} -#line 8395 "built/tmp/cppBison.yxx.c" - break; - - case 617: /* const_expr: KW_INT '(' optional_const_expr_comma ')' */ -#line 3595 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8405 "built/tmp/cppBison.yxx.c" - break; - - case 618: /* const_expr: KW_CHAR '(' optional_const_expr_comma ')' */ -#line 3601 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8415 "built/tmp/cppBison.yxx.c" - break; - - case 619: /* const_expr: KW_WCHAR_T '(' optional_const_expr_comma ')' */ -#line 3607 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8425 "built/tmp/cppBison.yxx.c" - break; - - case 620: /* const_expr: KW_CHAR8_T '(' optional_const_expr_comma ')' */ -#line 3613 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char8_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8435 "built/tmp/cppBison.yxx.c" - break; - - case 621: /* const_expr: KW_CHAR16_T '(' optional_const_expr_comma ')' */ -#line 3619 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8445 "built/tmp/cppBison.yxx.c" - break; - - case 622: /* const_expr: KW_CHAR32_T '(' optional_const_expr_comma ')' */ -#line 3625 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8455 "built/tmp/cppBison.yxx.c" - break; - - case 623: /* const_expr: KW_BOOL '(' optional_const_expr_comma ')' */ -#line 3631 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8465 "built/tmp/cppBison.yxx.c" - break; - - case 624: /* const_expr: KW_SHORT '(' optional_const_expr_comma ')' */ -#line 3637 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_short)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8476 "built/tmp/cppBison.yxx.c" - break; - - case 625: /* const_expr: KW_LONG '(' optional_const_expr_comma ')' */ -#line 3644 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_long)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8487 "built/tmp/cppBison.yxx.c" - break; - - case 626: /* const_expr: KW_UNSIGNED '(' optional_const_expr_comma ')' */ -#line 3651 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_unsigned)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8498 "built/tmp/cppBison.yxx.c" - break; - - case 627: /* const_expr: KW_SIGNED '(' optional_const_expr_comma ')' */ -#line 3658 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_signed)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8509 "built/tmp/cppBison.yxx.c" - break; - - case 628: /* const_expr: KW_FLOAT '(' optional_const_expr_comma ')' */ -#line 3665 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8519 "built/tmp/cppBison.yxx.c" - break; - - case 629: /* const_expr: KW_DOUBLE '(' optional_const_expr_comma ')' */ -#line 3671 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); - (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); -} -#line 8529 "built/tmp/cppBison.yxx.c" - break; - - case 630: /* const_expr: KW_SIZEOF '(' full_type ')' */ -#line 3677 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); -} -#line 8537 "built/tmp/cppBison.yxx.c" - break; - - case 631: /* const_expr: KW_SIZEOF const_expr */ -#line 3681 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[0].u.expr))); -} -#line 8545 "built/tmp/cppBison.yxx.c" - break; - - case 632: /* const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ -#line 3685 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_ellipsis_func((yyvsp[-1].u.identifier))); -} -#line 8553 "built/tmp/cppBison.yxx.c" - break; - - case 633: /* const_expr: KW_ALIGNOF '(' full_type ')' */ -#line 3689 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); -} -#line 8561 "built/tmp/cppBison.yxx.c" - break; - - case 634: /* const_expr: KW_NEW predefined_type */ -#line 3693 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[0].u.type))); -} -#line 8569 "built/tmp/cppBison.yxx.c" - break; - - case 635: /* const_expr: KW_NEW predefined_type '(' optional_const_expr_comma ')' */ -#line 3697 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[-3].u.type), (yyvsp[-1].u.expr))); -} -#line 8577 "built/tmp/cppBison.yxx.c" - break; - - case 636: /* const_expr: KW_TYPEID '(' full_type ')' */ -#line 3701 "dtool/src/cppparser/cppBison.yxx" -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[-3])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.type), std_type_info)); -} -#line 8592 "built/tmp/cppBison.yxx.c" - break; - - case 637: /* const_expr: KW_TYPEID '(' const_expr ')' */ -#line 3712 "dtool/src/cppparser/cppBison.yxx" -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[-3])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.expr), std_type_info)); -} -#line 8607 "built/tmp/cppBison.yxx.c" - break; - - case 638: /* const_expr: '!' const_expr */ -#line 3723 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); -} -#line 8615 "built/tmp/cppBison.yxx.c" - break; - - case 639: /* const_expr: '~' const_expr */ -#line 3727 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); -} -#line 8623 "built/tmp/cppBison.yxx.c" - break; - - case 640: /* const_expr: '-' const_expr */ -#line 3731 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); -} -#line 8631 "built/tmp/cppBison.yxx.c" - break; - - case 641: /* const_expr: '+' const_expr */ -#line 3735 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); -} -#line 8639 "built/tmp/cppBison.yxx.c" - break; - - case 642: /* const_expr: '*' const_expr */ -#line 3739 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[0].u.expr)); -} -#line 8647 "built/tmp/cppBison.yxx.c" - break; - - case 643: /* const_expr: '&' const_expr */ -#line 3743 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); -} -#line 8655 "built/tmp/cppBison.yxx.c" - break; - - case 644: /* const_expr: const_expr '*' const_expr */ -#line 3747 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8663 "built/tmp/cppBison.yxx.c" - break; - - case 645: /* const_expr: const_expr '/' const_expr */ -#line 3751 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8671 "built/tmp/cppBison.yxx.c" - break; - - case 646: /* const_expr: const_expr '%' const_expr */ -#line 3755 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8679 "built/tmp/cppBison.yxx.c" - break; - - case 647: /* const_expr: const_expr '+' const_expr */ -#line 3759 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8687 "built/tmp/cppBison.yxx.c" - break; - - case 648: /* const_expr: const_expr '-' const_expr */ -#line 3763 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8695 "built/tmp/cppBison.yxx.c" - break; - - case 649: /* const_expr: const_expr '|' const_expr */ -#line 3767 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8703 "built/tmp/cppBison.yxx.c" - break; - - case 650: /* const_expr: const_expr '^' const_expr */ -#line 3771 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8711 "built/tmp/cppBison.yxx.c" - break; - - case 651: /* const_expr: const_expr '&' const_expr */ -#line 3775 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8719 "built/tmp/cppBison.yxx.c" - break; - - case 652: /* const_expr: const_expr OROR const_expr */ -#line 3779 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8727 "built/tmp/cppBison.yxx.c" - break; - - case 653: /* const_expr: const_expr ANDAND const_expr */ -#line 3783 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8735 "built/tmp/cppBison.yxx.c" - break; - - case 654: /* const_expr: const_expr EQCOMPARE const_expr */ -#line 3787 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8743 "built/tmp/cppBison.yxx.c" - break; - - case 655: /* const_expr: const_expr NECOMPARE const_expr */ -#line 3791 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8751 "built/tmp/cppBison.yxx.c" - break; - - case 656: /* const_expr: const_expr LECOMPARE const_expr */ -#line 3795 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8759 "built/tmp/cppBison.yxx.c" - break; - - case 657: /* const_expr: const_expr GECOMPARE const_expr */ -#line 3799 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8767 "built/tmp/cppBison.yxx.c" - break; - - case 658: /* const_expr: const_expr SPACESHIP const_expr */ -#line 3803 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(SPACESHIP, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8775 "built/tmp/cppBison.yxx.c" - break; - - case 659: /* const_expr: const_expr '<' const_expr */ -#line 3807 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('<', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8783 "built/tmp/cppBison.yxx.c" - break; - - case 660: /* const_expr: const_expr '>' const_expr */ -#line 3811 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('>', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8791 "built/tmp/cppBison.yxx.c" - break; - - case 661: /* const_expr: const_expr LSHIFT const_expr */ -#line 3815 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8799 "built/tmp/cppBison.yxx.c" - break; - - case 662: /* const_expr: const_expr RSHIFT const_expr */ -#line 3819 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8807 "built/tmp/cppBison.yxx.c" - break; - - case 663: /* const_expr: const_expr '?' const_expr ':' const_expr */ -#line 3823 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8815 "built/tmp/cppBison.yxx.c" - break; - - case 664: /* const_expr: const_expr '[' const_expr ']' */ -#line 3827 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); -} -#line 8823 "built/tmp/cppBison.yxx.c" - break; - - case 665: /* const_expr: const_expr '(' const_expr_comma ')' */ -#line 3831 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); -} -#line 8831 "built/tmp/cppBison.yxx.c" - break; - - case 666: /* const_expr: const_expr '(' ')' */ -#line 3835 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); -} -#line 8839 "built/tmp/cppBison.yxx.c" - break; - - case 667: /* const_expr: KW_NOEXCEPT_LPAREN const_expr ')' */ -#line 3839 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(KW_NOEXCEPT, (yyvsp[-1].u.expr)); -} -#line 8847 "built/tmp/cppBison.yxx.c" - break; - - case 668: /* const_expr: const_expr '.' name */ -#line 3843 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer)); -} -#line 8855 "built/tmp/cppBison.yxx.c" - break; - - case 669: /* const_expr: const_expr POINTSAT const_expr */ -#line 3847 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 8863 "built/tmp/cppBison.yxx.c" - break; - - case 670: /* const_expr: '(' const_expr_comma ')' */ -#line 3851 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[-1].u.expr); -} -#line 8871 "built/tmp/cppBison.yxx.c" - break; - - case 671: /* const_operand: INTEGER */ -#line 3858 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); -} -#line 8879 "built/tmp/cppBison.yxx.c" - break; - - case 672: /* const_operand: KW_TRUE */ -#line 3862 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(true); -} -#line 8887 "built/tmp/cppBison.yxx.c" - break; - - case 673: /* const_operand: KW_FALSE */ -#line 3866 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(false); -} -#line 8895 "built/tmp/cppBison.yxx.c" - break; - - case 674: /* const_operand: CHAR_TOK */ -#line 3870 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); -} -#line 8903 "built/tmp/cppBison.yxx.c" - break; - - case 675: /* const_operand: REAL */ -#line 3874 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.real)); -} -#line 8911 "built/tmp/cppBison.yxx.c" - break; - - case 676: /* const_operand: string_literal */ -#line 3878 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 8919 "built/tmp/cppBison.yxx.c" - break; - - case 677: /* const_operand: CUSTOM_LITERAL */ -#line 3882 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 8927 "built/tmp/cppBison.yxx.c" - break; - - case 678: /* const_operand: IDENTIFIER */ -#line 3886 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer); -} -#line 8935 "built/tmp/cppBison.yxx.c" - break; - - case 679: /* const_operand: KW_FINAL */ -#line 3890 "dtool/src/cppparser/cppBison.yxx" -{ - // A variable named "final". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[0])); - (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} -#line 8945 "built/tmp/cppBison.yxx.c" - break; - - case 680: /* const_operand: KW_OVERRIDE */ -#line 3896 "dtool/src/cppparser/cppBison.yxx" -{ - // A variable named "override". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[0])); - (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} -#line 8955 "built/tmp/cppBison.yxx.c" - break; - - case 681: /* const_operand: KW_NULLPTR */ -#line 3902 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); -} -#line 8963 "built/tmp/cppBison.yxx.c" - break; - - case 682: /* const_operand: '[' capture_list ']' function_post optional_attributes maybe_trailing_return_type '{' code '}' */ -#line 3906 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-7].u.closure_type)->_flags = (yyvsp[-5].u.integer); - (yyvsp[-7].u.closure_type)->_attributes = (yyvsp[-4].attr_list); - (yyvsp[-7].u.closure_type)->_return_type = (yyvsp[-3].u.type); - (yyval.u.expr) = new CPPExpression(CPPExpression::lambda((yyvsp[-7].u.closure_type))); -} -#line 8974 "built/tmp/cppBison.yxx.c" - break; - - case 683: /* const_operand: '[' capture_list ']' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type '{' code '}' */ -#line 3913 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-10].u.closure_type)->_parameters = (yyvsp[-7].u.param_list); - (yyvsp[-10].u.closure_type)->_flags = (yyvsp[-5].u.integer); - (yyvsp[-10].u.closure_type)->_attributes = (yyvsp[-4].attr_list); - (yyvsp[-10].u.closure_type)->_return_type = (yyvsp[-3].u.type); - (yyval.u.expr) = new CPPExpression(CPPExpression::lambda((yyvsp[-10].u.closure_type))); -} -#line 8986 "built/tmp/cppBison.yxx.c" - break; - - case 684: /* const_operand: KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')' */ -#line 3921 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_HAS_VIRTUAL_DESTRUCTOR, (yyvsp[-1].u.type))); -} -#line 8994 "built/tmp/cppBison.yxx.c" - break; - - case 685: /* const_operand: KW_IS_ABSTRACT '(' full_type ')' */ -#line 3925 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_ABSTRACT, (yyvsp[-1].u.type))); -} -#line 9002 "built/tmp/cppBison.yxx.c" - break; - - case 686: /* const_operand: KW_IS_BASE_OF '(' full_type ',' full_type ')' */ -#line 3929 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, (yyvsp[-3].u.type), (yyvsp[-1].u.type))); -} -#line 9010 "built/tmp/cppBison.yxx.c" - break; - - case 687: /* const_operand: KW_IS_CLASS '(' full_type ')' */ -#line 3933 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, (yyvsp[-1].u.type))); -} -#line 9018 "built/tmp/cppBison.yxx.c" - break; - - case 688: /* const_operand: KW_IS_CONSTRUCTIBLE '(' full_type ')' */ -#line 3937 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, (yyvsp[-1].u.type))); -} -#line 9026 "built/tmp/cppBison.yxx.c" - break; - - case 689: /* const_operand: KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')' */ -#line 3941 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, (yyvsp[-3].u.type), (yyvsp[-1].u.type))); -} -#line 9034 "built/tmp/cppBison.yxx.c" - break; - - case 690: /* const_operand: KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')' */ -#line 3945 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CONVERTIBLE_TO, (yyvsp[-3].u.type), (yyvsp[-1].u.type))); -} -#line 9042 "built/tmp/cppBison.yxx.c" - break; - - case 691: /* const_operand: KW_IS_DESTRUCTIBLE '(' full_type ')' */ -#line 3949 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_DESTRUCTIBLE, (yyvsp[-1].u.type))); -} -#line 9050 "built/tmp/cppBison.yxx.c" - break; - - case 692: /* const_operand: KW_IS_EMPTY '(' full_type ')' */ -#line 3953 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_EMPTY, (yyvsp[-1].u.type))); -} -#line 9058 "built/tmp/cppBison.yxx.c" - break; - - case 693: /* const_operand: KW_IS_ENUM '(' full_type ')' */ -#line 3957 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_ENUM, (yyvsp[-1].u.type))); -} -#line 9066 "built/tmp/cppBison.yxx.c" - break; - - case 694: /* const_operand: KW_IS_FINAL '(' full_type ')' */ -#line 3961 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_FINAL, (yyvsp[-1].u.type))); -} -#line 9074 "built/tmp/cppBison.yxx.c" - break; - - case 695: /* const_operand: KW_IS_FUNDAMENTAL '(' full_type ')' */ -#line 3965 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_FUNDAMENTAL, (yyvsp[-1].u.type))); -} -#line 9082 "built/tmp/cppBison.yxx.c" - break; - - case 696: /* const_operand: KW_IS_POD '(' full_type ')' */ -#line 3969 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_POD, (yyvsp[-1].u.type))); -} -#line 9090 "built/tmp/cppBison.yxx.c" - break; - - case 697: /* const_operand: KW_IS_POLYMORPHIC '(' full_type ')' */ -#line 3973 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_POLYMORPHIC, (yyvsp[-1].u.type))); -} -#line 9098 "built/tmp/cppBison.yxx.c" - break; - - case 698: /* const_operand: KW_IS_STANDARD_LAYOUT '(' full_type ')' */ -#line 3977 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_STANDARD_LAYOUT, (yyvsp[-1].u.type))); -} -#line 9106 "built/tmp/cppBison.yxx.c" - break; - - case 699: /* const_operand: KW_IS_TRIVIAL '(' full_type ')' */ -#line 3981 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, (yyvsp[-1].u.type))); -} -#line 9114 "built/tmp/cppBison.yxx.c" - break; - - case 700: /* const_operand: KW_IS_TRIVIALLY_COPYABLE '(' full_type ')' */ -#line 3985 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIALLY_COPYABLE, (yyvsp[-1].u.type))); -} -#line 9122 "built/tmp/cppBison.yxx.c" - break; - - case 701: /* const_operand: KW_IS_UNION '(' full_type ')' */ -#line 3989 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_UNION, (yyvsp[-1].u.type))); -} -#line 9130 "built/tmp/cppBison.yxx.c" - break; - - case 702: /* formal_const_expr: formal_const_operand */ -#line 4003 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 9138 "built/tmp/cppBison.yxx.c" - break; - - case 703: /* formal_const_expr: '(' full_type ')' const_expr */ -#line 4007 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); -} -#line 9146 "built/tmp/cppBison.yxx.c" - break; - - case 704: /* formal_const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 4011 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); -} -#line 9154 "built/tmp/cppBison.yxx.c" - break; - - case 705: /* formal_const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 4015 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); -} -#line 9162 "built/tmp/cppBison.yxx.c" - break; - - case 706: /* formal_const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 4019 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); -} -#line 9170 "built/tmp/cppBison.yxx.c" - break; - - case 707: /* formal_const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 4023 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); -} -#line 9178 "built/tmp/cppBison.yxx.c" - break; - - case 708: /* formal_const_expr: KW_SIZEOF '(' full_type ')' */ -#line 4027 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); -} -#line 9186 "built/tmp/cppBison.yxx.c" - break; - - case 709: /* formal_const_expr: KW_SIZEOF formal_const_expr */ -#line 4031 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[0].u.expr))); -} -#line 9194 "built/tmp/cppBison.yxx.c" - break; - - case 710: /* formal_const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ -#line 4035 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_ellipsis_func((yyvsp[-1].u.identifier))); -} -#line 9202 "built/tmp/cppBison.yxx.c" - break; - - case 711: /* formal_const_expr: KW_ALIGNOF '(' full_type ')' */ -#line 4039 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); -} -#line 9210 "built/tmp/cppBison.yxx.c" - break; - - case 712: /* formal_const_expr: KW_NEW predefined_type */ -#line 4043 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[0].u.type))); -} -#line 9218 "built/tmp/cppBison.yxx.c" - break; - - case 713: /* formal_const_expr: KW_NEW predefined_type '(' optional_const_expr_comma ')' */ -#line 4047 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[-3].u.type), (yyvsp[-1].u.expr))); -} -#line 9226 "built/tmp/cppBison.yxx.c" - break; - - case 714: /* formal_const_expr: KW_TYPEID '(' full_type ')' */ -#line 4051 "dtool/src/cppparser/cppBison.yxx" -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[-3])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.type), std_type_info)); -} -#line 9241 "built/tmp/cppBison.yxx.c" - break; - - case 715: /* formal_const_expr: KW_TYPEID '(' const_expr ')' */ -#line 4062 "dtool/src/cppparser/cppBison.yxx" -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", (yylsp[-3])); - } - (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.expr), std_type_info)); -} -#line 9256 "built/tmp/cppBison.yxx.c" - break; - - case 716: /* formal_const_expr: '!' const_expr */ -#line 4073 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); -} -#line 9264 "built/tmp/cppBison.yxx.c" - break; - - case 717: /* formal_const_expr: '~' const_expr */ -#line 4077 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); -} -#line 9272 "built/tmp/cppBison.yxx.c" - break; - - case 718: /* formal_const_expr: '-' const_expr */ -#line 4081 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); -} -#line 9280 "built/tmp/cppBison.yxx.c" - break; - - case 719: /* formal_const_expr: '+' const_expr */ -#line 4085 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); -} -#line 9288 "built/tmp/cppBison.yxx.c" - break; - - case 720: /* formal_const_expr: '&' const_expr */ -#line 4089 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); -} -#line 9296 "built/tmp/cppBison.yxx.c" - break; - - case 721: /* formal_const_expr: formal_const_expr '*' const_expr */ -#line 4093 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9304 "built/tmp/cppBison.yxx.c" - break; - - case 722: /* formal_const_expr: formal_const_expr '/' const_expr */ -#line 4097 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9312 "built/tmp/cppBison.yxx.c" - break; - - case 723: /* formal_const_expr: formal_const_expr '%' const_expr */ -#line 4101 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9320 "built/tmp/cppBison.yxx.c" - break; - - case 724: /* formal_const_expr: formal_const_expr '+' const_expr */ -#line 4105 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9328 "built/tmp/cppBison.yxx.c" - break; - - case 725: /* formal_const_expr: formal_const_expr '-' const_expr */ -#line 4109 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9336 "built/tmp/cppBison.yxx.c" - break; - - case 726: /* formal_const_expr: formal_const_expr '|' const_expr */ -#line 4113 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9344 "built/tmp/cppBison.yxx.c" - break; - - case 727: /* formal_const_expr: formal_const_expr '^' const_expr */ -#line 4117 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9352 "built/tmp/cppBison.yxx.c" - break; - - case 728: /* formal_const_expr: formal_const_expr '&' const_expr */ -#line 4121 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9360 "built/tmp/cppBison.yxx.c" - break; - - case 729: /* formal_const_expr: formal_const_expr OROR const_expr */ -#line 4125 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9368 "built/tmp/cppBison.yxx.c" - break; - - case 730: /* formal_const_expr: formal_const_expr ANDAND const_expr */ -#line 4129 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9376 "built/tmp/cppBison.yxx.c" - break; - - case 731: /* formal_const_expr: formal_const_expr EQCOMPARE const_expr */ -#line 4133 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9384 "built/tmp/cppBison.yxx.c" - break; - - case 732: /* formal_const_expr: formal_const_expr NECOMPARE const_expr */ -#line 4137 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9392 "built/tmp/cppBison.yxx.c" - break; - - case 733: /* formal_const_expr: formal_const_expr LECOMPARE const_expr */ -#line 4141 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9400 "built/tmp/cppBison.yxx.c" - break; - - case 734: /* formal_const_expr: formal_const_expr GECOMPARE const_expr */ -#line 4145 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9408 "built/tmp/cppBison.yxx.c" - break; - - case 735: /* formal_const_expr: formal_const_expr SPACESHIP const_expr */ -#line 4149 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(SPACESHIP, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9416 "built/tmp/cppBison.yxx.c" - break; - - case 736: /* formal_const_expr: formal_const_expr '<' const_expr */ -#line 4153 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('<', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9424 "built/tmp/cppBison.yxx.c" - break; - - case 737: /* formal_const_expr: formal_const_expr '>' const_expr */ -#line 4157 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('>', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9432 "built/tmp/cppBison.yxx.c" - break; - - case 738: /* formal_const_expr: formal_const_expr LSHIFT const_expr */ -#line 4161 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9440 "built/tmp/cppBison.yxx.c" - break; - - case 739: /* formal_const_expr: formal_const_expr RSHIFT const_expr */ -#line 4165 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9448 "built/tmp/cppBison.yxx.c" - break; - - case 740: /* formal_const_expr: formal_const_expr '?' const_expr ':' const_expr */ -#line 4169 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9456 "built/tmp/cppBison.yxx.c" - break; - - case 741: /* formal_const_expr: formal_const_expr '[' const_expr ']' */ -#line 4173 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); -} -#line 9464 "built/tmp/cppBison.yxx.c" - break; - - case 742: /* formal_const_expr: formal_const_expr '(' const_expr_comma ')' */ -#line 4177 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); -} -#line 9472 "built/tmp/cppBison.yxx.c" - break; - - case 743: /* formal_const_expr: formal_const_expr '(' ')' */ -#line 4181 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); -} -#line 9480 "built/tmp/cppBison.yxx.c" - break; - - case 744: /* formal_const_expr: formal_const_expr '.' name */ -#line 4185 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer)); -} -#line 9488 "built/tmp/cppBison.yxx.c" - break; - - case 745: /* formal_const_expr: formal_const_expr POINTSAT const_expr */ -#line 4189 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); -} -#line 9496 "built/tmp/cppBison.yxx.c" - break; - - case 746: /* formal_const_expr: '(' const_expr_comma ')' */ -#line 4193 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[-1].u.expr); -} -#line 9504 "built/tmp/cppBison.yxx.c" - break; - - case 747: /* formal_const_operand: INTEGER */ -#line 4200 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); -} -#line 9512 "built/tmp/cppBison.yxx.c" - break; - - case 748: /* formal_const_operand: KW_TRUE */ -#line 4204 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(true); -} -#line 9520 "built/tmp/cppBison.yxx.c" - break; - - case 749: /* formal_const_operand: KW_FALSE */ -#line 4208 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(false); -} -#line 9528 "built/tmp/cppBison.yxx.c" - break; - - case 750: /* formal_const_operand: CHAR_TOK */ -#line 4212 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); -} -#line 9536 "built/tmp/cppBison.yxx.c" - break; - - case 751: /* formal_const_operand: REAL */ -#line 4216 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.real)); -} -#line 9544 "built/tmp/cppBison.yxx.c" - break; - - case 752: /* formal_const_operand: string_literal */ -#line 4220 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 9552 "built/tmp/cppBison.yxx.c" - break; - - case 753: /* formal_const_operand: CUSTOM_LITERAL */ -#line 4224 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 9560 "built/tmp/cppBison.yxx.c" - break; - - case 754: /* formal_const_operand: IDENTIFIER */ -#line 4228 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer); -} -#line 9568 "built/tmp/cppBison.yxx.c" - break; - - case 755: /* formal_const_operand: KW_FINAL */ -#line 4232 "dtool/src/cppparser/cppBison.yxx" -{ - // A variable named "final". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[0])); - (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} -#line 9578 "built/tmp/cppBison.yxx.c" - break; - - case 756: /* formal_const_operand: KW_OVERRIDE */ -#line 4238 "dtool/src/cppparser/cppBison.yxx" -{ - // A variable named "override". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[0])); - (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} -#line 9588 "built/tmp/cppBison.yxx.c" - break; - - case 757: /* formal_const_operand: KW_NULLPTR */ -#line 4244 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); -} -#line 9596 "built/tmp/cppBison.yxx.c" - break; - - case 758: /* capture_list: empty */ -#line 4252 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.closure_type) = new CPPClosureType(); -} -#line 9604 "built/tmp/cppBison.yxx.c" - break; - - case 759: /* capture_list: '=' */ -#line 4256 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.closure_type) = new CPPClosureType(CPPClosureType::CT_by_value); -} -#line 9612 "built/tmp/cppBison.yxx.c" - break; - - case 760: /* capture_list: '&' */ -#line 4260 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.closure_type) = new CPPClosureType(CPPClosureType::CT_by_reference); -} -#line 9620 "built/tmp/cppBison.yxx.c" - break; - - case 761: /* capture_list: capture maybe_initialize */ -#line 4264 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.closure_type) = new CPPClosureType(); - (yyvsp[-1].u.capture)->_initializer = (yyvsp[0].u.expr); - (yyval.u.closure_type)->_captures.push_back(*(yyvsp[-1].u.capture)); - delete (yyvsp[-1].u.capture); -} -#line 9631 "built/tmp/cppBison.yxx.c" - break; - - case 762: /* capture_list: capture_list ',' capture maybe_initialize */ -#line 4271 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.closure_type) = (yyvsp[-3].u.closure_type); - (yyvsp[-1].u.capture)->_initializer = (yyvsp[0].u.expr); - (yyval.u.closure_type)->_captures.push_back(*(yyvsp[-1].u.capture)); - delete (yyvsp[-1].u.capture); -} -#line 9642 "built/tmp/cppBison.yxx.c" - break; - - case 763: /* capture: '&' name */ -#line 4281 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.capture) = new CPPClosureType::Capture; - (yyval.u.capture)->_name = (yyvsp[0].u.identifier)->get_simple_name(); - (yyval.u.capture)->_type = CPPClosureType::CT_by_reference; -} -#line 9652 "built/tmp/cppBison.yxx.c" - break; - - case 764: /* capture: '&' name ELLIPSIS */ -#line 4287 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.capture) = new CPPClosureType::Capture; - (yyval.u.capture)->_name = (yyvsp[-1].u.identifier)->get_simple_name(); - (yyval.u.capture)->_type = CPPClosureType::CT_by_reference; -} -#line 9662 "built/tmp/cppBison.yxx.c" - break; - - case 765: /* capture: name */ -#line 4293 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.capture) = new CPPClosureType::Capture; - (yyval.u.capture)->_name = (yyvsp[0].u.identifier)->get_simple_name(); - if ((yyval.u.capture)->_name == "this") { - (yyval.u.capture)->_type = CPPClosureType::CT_by_reference; - } else { - (yyval.u.capture)->_type = CPPClosureType::CT_by_value; - } -} -#line 9676 "built/tmp/cppBison.yxx.c" - break; - - case 766: /* capture: '*' name */ -#line 4303 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.capture) = new CPPClosureType::Capture; - (yyval.u.capture)->_name = (yyvsp[0].u.identifier)->get_simple_name(); - (yyval.u.capture)->_type = CPPClosureType::CT_by_value; - if ((yyval.u.capture)->_name != "this") { - yywarning("only capture name 'this' may be preceded by an asterisk", (yylsp[0])); - } -} -#line 9689 "built/tmp/cppBison.yxx.c" - break; - - case 767: /* class_derivation_name: name */ -#line 4315 "dtool/src/cppparser/cppBison.yxx" -{ - CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, true); - if (type == nullptr) { - type = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); - } - (yyval.u.type) = type; -} -#line 9701 "built/tmp/cppBison.yxx.c" - break; - - case 768: /* class_derivation_name: KW_TYPENAME name */ -#line 4323 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); -} -#line 9709 "built/tmp/cppBison.yxx.c" - break; - - case 769: /* class_derivation_name: name ELLIPSIS */ -#line 4327 "dtool/src/cppparser/cppBison.yxx" -{ - CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((yyvsp[-1].u.identifier)); - ctp->_packed = true; - (yyval.u.type) = CPPType::new_type(ctp); -} -#line 9719 "built/tmp/cppBison.yxx.c" - break; - - case 770: /* name: IDENTIFIER */ -#line 4357 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 9727 "built/tmp/cppBison.yxx.c" - break; - - case 771: /* name: TYPENAME_IDENTIFIER */ -#line 4361 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 9735 "built/tmp/cppBison.yxx.c" - break; - - case 772: /* name: TYPEPACK_IDENTIFIER */ -#line 4365 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 9743 "built/tmp/cppBison.yxx.c" - break; - - case 773: /* name: KW_FINAL */ -#line 4369 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("final", (yylsp[0])); -} -#line 9751 "built/tmp/cppBison.yxx.c" - break; - - case 774: /* name: KW_OVERRIDE */ -#line 4373 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[0])); -} -#line 9759 "built/tmp/cppBison.yxx.c" - break; - - case 775: /* name: KW_SIGNED */ -#line 4377 "dtool/src/cppparser/cppBison.yxx" -{ - // This is not a keyword in Python, so it is useful to be able to use this - // in MAKE_PROPERTY definitions, etc. - (yyval.u.identifier) = new CPPIdentifier("signed", (yylsp[0])); -} -#line 9769 "built/tmp/cppBison.yxx.c" - break; - - case 776: /* name: KW_FLOAT */ -#line 4383 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("float", (yylsp[0])); -} -#line 9777 "built/tmp/cppBison.yxx.c" - break; - - case 777: /* name: KW_PUBLIC */ -#line 4387 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("public", (yylsp[0])); -} -#line 9785 "built/tmp/cppBison.yxx.c" - break; - - case 778: /* name: KW_PRIVATE */ -#line 4391 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("private", (yylsp[0])); -} -#line 9793 "built/tmp/cppBison.yxx.c" - break; - - case 779: /* name: KW_STATIC */ -#line 4395 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("static", (yylsp[0])); -} -#line 9801 "built/tmp/cppBison.yxx.c" - break; - - case 780: /* name: KW_DEFAULT */ -#line 4399 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("default", (yylsp[0])); -} -#line 9809 "built/tmp/cppBison.yxx.c" - break; - - case 781: /* name_no_final: IDENTIFIER */ -#line 4410 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 9817 "built/tmp/cppBison.yxx.c" - break; - - case 782: /* name_no_final: TYPENAME_IDENTIFIER */ -#line 4414 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 9825 "built/tmp/cppBison.yxx.c" - break; - - case 783: /* name_no_final: TYPEPACK_IDENTIFIER */ -#line 4418 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 9833 "built/tmp/cppBison.yxx.c" - break; - - case 784: /* name_no_final: KW_OVERRIDE */ -#line 4422 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[0])); -} -#line 9841 "built/tmp/cppBison.yxx.c" - break; - - case 785: /* string_literal: SIMPLE_STRING */ -#line 4430 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = new CPPExpression((yyvsp[0].str)); -} -#line 9849 "built/tmp/cppBison.yxx.c" - break; - - case 786: /* string_literal: STRING_LITERAL */ -#line 4434 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 9857 "built/tmp/cppBison.yxx.c" - break; - - case 787: /* string_literal: string_literal SIMPLE_STRING */ -#line 4438 "dtool/src/cppparser/cppBison.yxx" -{ - // The right string takes on the literal type of the left. - (yyval.u.expr) = (yyvsp[-1].u.expr); - (yyval.u.expr)->_str += (yyvsp[0].str); -} -#line 9867 "built/tmp/cppBison.yxx.c" - break; - - case 788: /* string_literal: string_literal STRING_LITERAL */ -#line 4444 "dtool/src/cppparser/cppBison.yxx" -{ - // We have to check that the two literal types match up. - (yyval.u.expr) = (yyvsp[-1].u.expr); - if ((yyvsp[0].u.expr)->_type != CPPExpression::T_string && (yyvsp[0].u.expr)->_type != (yyvsp[-1].u.expr)->_type) { - yywarning("cannot concatenate two string literals of different types", (yyloc)); - } - (yyval.u.expr)->_str += (yyvsp[0].u.expr)->_str; -} -#line 9880 "built/tmp/cppBison.yxx.c" - break; - - -#line 9884 "built/tmp/cppBison.yxx.c" - - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - - *++yyvsp = yyval; - *++yylsp = yyloc; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - { - const int yylhs = yyr1[yyn] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyssp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - yyerror (&yylloc, YY_("syntax error")); - } - - yyerror_range[1] = yylloc; - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - /* Pacify compilers when the user code never invokes YYERROR and the - label yyerrorlab therefore never appears in user code. */ - if (0) - YYERROR; - ++yynerrs; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - /* Pop stack until we find a state that shifts the error token. */ - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYSYMBOL_YYerror; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - yyerror_range[1] = *yylsp; - yydestruct ("Error: popping", - YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - yyerror_range[2] = yylloc; - ++yylsp; - YYLLOC_DEFAULT (*yylsp, yyerror_range, 2); - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturnlab; - - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturnlab; - - -/*-----------------------------------------------------------. -| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | -`-----------------------------------------------------------*/ -yyexhaustedlab: - yyerror (&yylloc, YY_("memory exhausted")); - yyresult = 2; - goto yyreturnlab; - - -/*----------------------------------------------------------. -| yyreturnlab -- parsing is finished, clean up and return. | -`----------------------------------------------------------*/ -yyreturnlab: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - - return yyresult; -} - diff --git a/dtool/src/cppparser/cppBison.h.prebuilt b/dtool/src/cppparser/cppBison.h.prebuilt deleted file mode 100644 index 78032c0153..0000000000 --- a/dtool/src/cppparser/cppBison.h.prebuilt +++ /dev/null @@ -1,394 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.8.2. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -#ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED -# define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int cppyydebug; -#endif - -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - YYEMPTY = -2, - YYEOF = 0, /* "end of file" */ - YYerror = 256, /* error */ - YYUNDEF = 257, /* "invalid token" */ - REAL = 258, /* REAL */ - INTEGER = 259, /* INTEGER */ - CHAR_TOK = 260, /* CHAR_TOK */ - SIMPLE_STRING = 261, /* SIMPLE_STRING */ - SIMPLE_IDENTIFIER = 262, /* SIMPLE_IDENTIFIER */ - STRING_LITERAL = 263, /* STRING_LITERAL */ - CUSTOM_LITERAL = 264, /* CUSTOM_LITERAL */ - IDENTIFIER = 265, /* IDENTIFIER */ - TYPENAME_IDENTIFIER = 266, /* TYPENAME_IDENTIFIER */ - TYPEPACK_IDENTIFIER = 267, /* TYPEPACK_IDENTIFIER */ - SCOPING = 268, /* SCOPING */ - TYPEDEFNAME = 269, /* TYPEDEFNAME */ - ELLIPSIS = 270, /* ELLIPSIS */ - OROR = 271, /* OROR */ - ANDAND = 272, /* ANDAND */ - EQCOMPARE = 273, /* EQCOMPARE */ - NECOMPARE = 274, /* NECOMPARE */ - LECOMPARE = 275, /* LECOMPARE */ - GECOMPARE = 276, /* GECOMPARE */ - SPACESHIP = 277, /* SPACESHIP */ - LSHIFT = 278, /* LSHIFT */ - RSHIFT = 279, /* RSHIFT */ - POINTSAT_STAR = 280, /* POINTSAT_STAR */ - DOT_STAR = 281, /* DOT_STAR */ - UNARY = 282, /* UNARY */ - UNARY_NOT = 283, /* UNARY_NOT */ - UNARY_NEGATE = 284, /* UNARY_NEGATE */ - UNARY_MINUS = 285, /* UNARY_MINUS */ - UNARY_PLUS = 286, /* UNARY_PLUS */ - UNARY_STAR = 287, /* UNARY_STAR */ - UNARY_REF = 288, /* UNARY_REF */ - POINTSAT = 289, /* POINTSAT */ - SCOPE = 290, /* SCOPE */ - PLUSPLUS = 291, /* PLUSPLUS */ - MINUSMINUS = 292, /* MINUSMINUS */ - TIMESEQUAL = 293, /* TIMESEQUAL */ - DIVIDEEQUAL = 294, /* DIVIDEEQUAL */ - MODEQUAL = 295, /* MODEQUAL */ - PLUSEQUAL = 296, /* PLUSEQUAL */ - MINUSEQUAL = 297, /* MINUSEQUAL */ - OREQUAL = 298, /* OREQUAL */ - ANDEQUAL = 299, /* ANDEQUAL */ - XOREQUAL = 300, /* XOREQUAL */ - LSHIFTEQUAL = 301, /* LSHIFTEQUAL */ - RSHIFTEQUAL = 302, /* RSHIFTEQUAL */ - ATTR_LEFT = 303, /* ATTR_LEFT */ - ATTR_RIGHT = 304, /* ATTR_RIGHT */ - KW_ALIGNAS = 305, /* KW_ALIGNAS */ - KW_ALIGNOF = 306, /* KW_ALIGNOF */ - KW_AUTO = 307, /* KW_AUTO */ - KW_BEGIN_PUBLISH = 308, /* KW_BEGIN_PUBLISH */ - KW_BLOCKING = 309, /* KW_BLOCKING */ - KW_BOOL = 310, /* KW_BOOL */ - KW_BUILTIN_VA_LIST = 311, /* KW_BUILTIN_VA_LIST */ - KW_CATCH = 312, /* KW_CATCH */ - KW_CHAR = 313, /* KW_CHAR */ - KW_CHAR8_T = 314, /* KW_CHAR8_T */ - KW_CHAR16_T = 315, /* KW_CHAR16_T */ - KW_CHAR32_T = 316, /* KW_CHAR32_T */ - KW_CLASS = 317, /* KW_CLASS */ - KW_CONST = 318, /* KW_CONST */ - KW_CONSTEVAL = 319, /* KW_CONSTEVAL */ - KW_CONSTEXPR = 320, /* KW_CONSTEXPR */ - KW_CONSTINIT = 321, /* KW_CONSTINIT */ - KW_CONST_CAST = 322, /* KW_CONST_CAST */ - KW_DECLTYPE = 323, /* KW_DECLTYPE */ - KW_DEFAULT = 324, /* KW_DEFAULT */ - KW_DELETE = 325, /* KW_DELETE */ - KW_DOUBLE = 326, /* KW_DOUBLE */ - KW_DYNAMIC_CAST = 327, /* KW_DYNAMIC_CAST */ - KW_ELSE = 328, /* KW_ELSE */ - KW_END_PUBLISH = 329, /* KW_END_PUBLISH */ - KW_ENUM = 330, /* KW_ENUM */ - KW_EXTENSION = 331, /* KW_EXTENSION */ - KW_EXTERN = 332, /* KW_EXTERN */ - KW_EXPLICIT = 333, /* KW_EXPLICIT */ - KW_EXPLICIT_LPAREN = 334, /* KW_EXPLICIT_LPAREN */ - KW_PUBLISHED = 335, /* KW_PUBLISHED */ - KW_FALSE = 336, /* KW_FALSE */ - KW_FINAL = 337, /* KW_FINAL */ - KW_FLOAT = 338, /* KW_FLOAT */ - KW_FRIEND = 339, /* KW_FRIEND */ - KW_FOR = 340, /* KW_FOR */ - KW_GOTO = 341, /* KW_GOTO */ - KW_HAS_VIRTUAL_DESTRUCTOR = 342, /* KW_HAS_VIRTUAL_DESTRUCTOR */ - KW_IF = 343, /* KW_IF */ - KW_INLINE = 344, /* KW_INLINE */ - KW_INT = 345, /* KW_INT */ - KW_IS_ABSTRACT = 346, /* KW_IS_ABSTRACT */ - KW_IS_BASE_OF = 347, /* KW_IS_BASE_OF */ - KW_IS_CLASS = 348, /* KW_IS_CLASS */ - KW_IS_CONSTRUCTIBLE = 349, /* KW_IS_CONSTRUCTIBLE */ - KW_IS_CONVERTIBLE_TO = 350, /* KW_IS_CONVERTIBLE_TO */ - KW_IS_DESTRUCTIBLE = 351, /* KW_IS_DESTRUCTIBLE */ - KW_IS_EMPTY = 352, /* KW_IS_EMPTY */ - KW_IS_ENUM = 353, /* KW_IS_ENUM */ - KW_IS_FINAL = 354, /* KW_IS_FINAL */ - KW_IS_FUNDAMENTAL = 355, /* KW_IS_FUNDAMENTAL */ - KW_IS_POD = 356, /* KW_IS_POD */ - KW_IS_POLYMORPHIC = 357, /* KW_IS_POLYMORPHIC */ - KW_IS_STANDARD_LAYOUT = 358, /* KW_IS_STANDARD_LAYOUT */ - KW_IS_TRIVIAL = 359, /* KW_IS_TRIVIAL */ - KW_IS_TRIVIALLY_COPYABLE = 360, /* KW_IS_TRIVIALLY_COPYABLE */ - KW_IS_UNION = 361, /* KW_IS_UNION */ - KW_LONG = 362, /* KW_LONG */ - KW_MAKE_MAP_KEYS_SEQ = 363, /* KW_MAKE_MAP_KEYS_SEQ */ - KW_MAKE_MAP_PROPERTY = 364, /* KW_MAKE_MAP_PROPERTY */ - KW_MAKE_PROPERTY = 365, /* KW_MAKE_PROPERTY */ - KW_MAKE_PROPERTY2 = 366, /* KW_MAKE_PROPERTY2 */ - KW_MAKE_SEQ = 367, /* KW_MAKE_SEQ */ - KW_MAKE_SEQ_PROPERTY = 368, /* KW_MAKE_SEQ_PROPERTY */ - KW_MUTABLE = 369, /* KW_MUTABLE */ - KW_NAMESPACE = 370, /* KW_NAMESPACE */ - KW_NEW = 371, /* KW_NEW */ - KW_NOEXCEPT = 372, /* KW_NOEXCEPT */ - KW_NOEXCEPT_LPAREN = 373, /* KW_NOEXCEPT_LPAREN */ - KW_NULLPTR = 374, /* KW_NULLPTR */ - KW_OPERATOR = 375, /* KW_OPERATOR */ - KW_OVERRIDE = 376, /* KW_OVERRIDE */ - KW_PRIVATE = 377, /* KW_PRIVATE */ - KW_PROTECTED = 378, /* KW_PROTECTED */ - KW_PUBLIC = 379, /* KW_PUBLIC */ - KW_REGISTER = 380, /* KW_REGISTER */ - KW_REINTERPRET_CAST = 381, /* KW_REINTERPRET_CAST */ - KW_RESTRICT = 382, /* KW_RESTRICT */ - KW_RETURN = 383, /* KW_RETURN */ - KW_SHORT = 384, /* KW_SHORT */ - KW_SIGNED = 385, /* KW_SIGNED */ - KW_SIZEOF = 386, /* KW_SIZEOF */ - KW_STATIC = 387, /* KW_STATIC */ - KW_STATIC_ASSERT = 388, /* KW_STATIC_ASSERT */ - KW_STATIC_CAST = 389, /* KW_STATIC_CAST */ - KW_STRUCT = 390, /* KW_STRUCT */ - KW_TEMPLATE = 391, /* KW_TEMPLATE */ - KW_THREAD_LOCAL = 392, /* KW_THREAD_LOCAL */ - KW_THROW = 393, /* KW_THROW */ - KW_TRUE = 394, /* KW_TRUE */ - KW_TRY = 395, /* KW_TRY */ - KW_TYPEDEF = 396, /* KW_TYPEDEF */ - KW_TYPEID = 397, /* KW_TYPEID */ - KW_TYPENAME = 398, /* KW_TYPENAME */ - KW_UNDERLYING_TYPE = 399, /* KW_UNDERLYING_TYPE */ - KW_UNION = 400, /* KW_UNION */ - KW_UNSIGNED = 401, /* KW_UNSIGNED */ - KW_USING = 402, /* KW_USING */ - KW_VIRTUAL = 403, /* KW_VIRTUAL */ - KW_VOID = 404, /* KW_VOID */ - KW_VOLATILE = 405, /* KW_VOLATILE */ - KW_WCHAR_T = 406, /* KW_WCHAR_T */ - KW_WHILE = 407, /* KW_WHILE */ - START_CPP = 408, /* START_CPP */ - START_CONST_EXPR = 409, /* START_CONST_EXPR */ - START_TYPE = 410 /* START_TYPE */ - }; - typedef enum yytokentype yytoken_kind_t; -#endif -/* Token kinds. */ -#define YYEMPTY -2 -#define YYEOF 0 -#define YYerror 256 -#define YYUNDEF 257 -#define REAL 258 -#define INTEGER 259 -#define CHAR_TOK 260 -#define SIMPLE_STRING 261 -#define SIMPLE_IDENTIFIER 262 -#define STRING_LITERAL 263 -#define CUSTOM_LITERAL 264 -#define IDENTIFIER 265 -#define TYPENAME_IDENTIFIER 266 -#define TYPEPACK_IDENTIFIER 267 -#define SCOPING 268 -#define TYPEDEFNAME 269 -#define ELLIPSIS 270 -#define OROR 271 -#define ANDAND 272 -#define EQCOMPARE 273 -#define NECOMPARE 274 -#define LECOMPARE 275 -#define GECOMPARE 276 -#define SPACESHIP 277 -#define LSHIFT 278 -#define RSHIFT 279 -#define POINTSAT_STAR 280 -#define DOT_STAR 281 -#define UNARY 282 -#define UNARY_NOT 283 -#define UNARY_NEGATE 284 -#define UNARY_MINUS 285 -#define UNARY_PLUS 286 -#define UNARY_STAR 287 -#define UNARY_REF 288 -#define POINTSAT 289 -#define SCOPE 290 -#define PLUSPLUS 291 -#define MINUSMINUS 292 -#define TIMESEQUAL 293 -#define DIVIDEEQUAL 294 -#define MODEQUAL 295 -#define PLUSEQUAL 296 -#define MINUSEQUAL 297 -#define OREQUAL 298 -#define ANDEQUAL 299 -#define XOREQUAL 300 -#define LSHIFTEQUAL 301 -#define RSHIFTEQUAL 302 -#define ATTR_LEFT 303 -#define ATTR_RIGHT 304 -#define KW_ALIGNAS 305 -#define KW_ALIGNOF 306 -#define KW_AUTO 307 -#define KW_BEGIN_PUBLISH 308 -#define KW_BLOCKING 309 -#define KW_BOOL 310 -#define KW_BUILTIN_VA_LIST 311 -#define KW_CATCH 312 -#define KW_CHAR 313 -#define KW_CHAR8_T 314 -#define KW_CHAR16_T 315 -#define KW_CHAR32_T 316 -#define KW_CLASS 317 -#define KW_CONST 318 -#define KW_CONSTEVAL 319 -#define KW_CONSTEXPR 320 -#define KW_CONSTINIT 321 -#define KW_CONST_CAST 322 -#define KW_DECLTYPE 323 -#define KW_DEFAULT 324 -#define KW_DELETE 325 -#define KW_DOUBLE 326 -#define KW_DYNAMIC_CAST 327 -#define KW_ELSE 328 -#define KW_END_PUBLISH 329 -#define KW_ENUM 330 -#define KW_EXTENSION 331 -#define KW_EXTERN 332 -#define KW_EXPLICIT 333 -#define KW_EXPLICIT_LPAREN 334 -#define KW_PUBLISHED 335 -#define KW_FALSE 336 -#define KW_FINAL 337 -#define KW_FLOAT 338 -#define KW_FRIEND 339 -#define KW_FOR 340 -#define KW_GOTO 341 -#define KW_HAS_VIRTUAL_DESTRUCTOR 342 -#define KW_IF 343 -#define KW_INLINE 344 -#define KW_INT 345 -#define KW_IS_ABSTRACT 346 -#define KW_IS_BASE_OF 347 -#define KW_IS_CLASS 348 -#define KW_IS_CONSTRUCTIBLE 349 -#define KW_IS_CONVERTIBLE_TO 350 -#define KW_IS_DESTRUCTIBLE 351 -#define KW_IS_EMPTY 352 -#define KW_IS_ENUM 353 -#define KW_IS_FINAL 354 -#define KW_IS_FUNDAMENTAL 355 -#define KW_IS_POD 356 -#define KW_IS_POLYMORPHIC 357 -#define KW_IS_STANDARD_LAYOUT 358 -#define KW_IS_TRIVIAL 359 -#define KW_IS_TRIVIALLY_COPYABLE 360 -#define KW_IS_UNION 361 -#define KW_LONG 362 -#define KW_MAKE_MAP_KEYS_SEQ 363 -#define KW_MAKE_MAP_PROPERTY 364 -#define KW_MAKE_PROPERTY 365 -#define KW_MAKE_PROPERTY2 366 -#define KW_MAKE_SEQ 367 -#define KW_MAKE_SEQ_PROPERTY 368 -#define KW_MUTABLE 369 -#define KW_NAMESPACE 370 -#define KW_NEW 371 -#define KW_NOEXCEPT 372 -#define KW_NOEXCEPT_LPAREN 373 -#define KW_NULLPTR 374 -#define KW_OPERATOR 375 -#define KW_OVERRIDE 376 -#define KW_PRIVATE 377 -#define KW_PROTECTED 378 -#define KW_PUBLIC 379 -#define KW_REGISTER 380 -#define KW_REINTERPRET_CAST 381 -#define KW_RESTRICT 382 -#define KW_RETURN 383 -#define KW_SHORT 384 -#define KW_SIGNED 385 -#define KW_SIZEOF 386 -#define KW_STATIC 387 -#define KW_STATIC_ASSERT 388 -#define KW_STATIC_CAST 389 -#define KW_STRUCT 390 -#define KW_TEMPLATE 391 -#define KW_THREAD_LOCAL 392 -#define KW_THROW 393 -#define KW_TRUE 394 -#define KW_TRY 395 -#define KW_TYPEDEF 396 -#define KW_TYPEID 397 -#define KW_TYPENAME 398 -#define KW_UNDERLYING_TYPE 399 -#define KW_UNION 400 -#define KW_UNSIGNED 401 -#define KW_USING 402 -#define KW_VIRTUAL 403 -#define KW_VOID 404 -#define KW_VOLATILE 405 -#define KW_WCHAR_T 406 -#define KW_WHILE 407 -#define START_CPP 408 -#define START_CONST_EXPR 409 -#define START_TYPE 410 - -/* Value type. */ - -/* Location type. */ -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE YYLTYPE; -struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -}; -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - - - - -int cppyyparse (void); - - -#endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED */ diff --git a/dtool/src/cppparser/cppBison.yxx b/dtool/src/cppparser/cppBison.yxx deleted file mode 100644 index 8a249d1185..0000000000 --- a/dtool/src/cppparser/cppBison.yxx +++ /dev/null @@ -1,4455 +0,0 @@ -/** - * @file cppBison.yxx - * @author drose - * @date 1999-01-16 - */ - -%{ - -#include "cppBisonDefs.h" -#include "cppParser.h" -#include "cppClosureType.h" -#include "cppExpression.h" -#include "cppSimpleType.h" -#include "cppExtensionType.h" -#include "cppStructType.h" -#include "cppEnumType.h" -#include "cppFunctionType.h" -#include "cppTBDType.h" -#include "cppMakeProperty.h" -#include "cppMakeSeq.h" -#include "cppParameterList.h" -#include "cppInstance.h" -#include "cppClassTemplateParameter.h" -#include "cppTemplateParameterList.h" -#include "cppInstanceIdentifier.h" -#include "cppTypedefType.h" -#include "cppTypeDeclaration.h" -#include "cppVisibility.h" -#include "cppIdentifier.h" -#include "cppScope.h" -#include "cppTemplateScope.h" -#include "cppNamespace.h" -#include "cppUsing.h" - -using std::stringstream; -using std::string; - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the parser. -//////////////////////////////////////////////////////////////////// - -CPPScope *current_scope = nullptr; -CPPScope *global_scope = nullptr; -CPPPreprocessor *current_lexer = nullptr; - -static CPPStructType *current_struct = nullptr; -static CPPEnumType *current_enum = nullptr; -static int current_storage_class = 0; -static CPPType *current_type = nullptr; -static CPPExpression *current_expr = nullptr; -static CPPAttributeList current_attributes; -static int publish_nest_level = 0; -static CPPVisibility publish_previous; -static YYLTYPE publish_loc; - -static std::vector last_scopes; -static std::vector last_storage_classes; -static std::vector last_structs; - -int yyparse(); - -#define YYERROR_VERBOSE - -static void -yyerror(const string &msg) { - current_lexer->error(msg, current_lexer->_last_token_loc); -} - -static void -yyerror(YYLTYPE *loc, const string &msg) { - current_lexer->error(msg, *loc); -} - -static void -yyerror(const string &msg, YYLTYPE &loc) { - current_lexer->error(msg, loc); -} - -static void -yywarning(const string &msg, YYLTYPE &loc) { - current_lexer->warning(msg, loc); -} - -static int -yylex(YYSTYPE *lval, YYLTYPE *lloc) { - CPPToken token = current_lexer->get_next_token(); - *lval = token._lval; - *lloc = token._lloc; - return token._token; -} - -void -parse_cpp(CPPParser *cp) { - CPPScope *old_scope = current_scope; - CPPScope *old_global_scope = global_scope; - CPPPreprocessor *old_lexer = current_lexer; - - current_scope = cp; - global_scope = cp; - current_lexer = cp; - publish_nest_level = 0; - yyparse(); - - if (publish_nest_level != 0) { - yyerror("Unclosed __begin_publish", publish_loc); - publish_nest_level = 0; - } - - current_scope = old_scope; - global_scope = old_global_scope; - current_lexer = old_lexer; - -} - -CPPExpression * -parse_const_expr(CPPPreprocessor *pp, CPPScope *new_current_scope, - CPPScope *new_global_scope) { - CPPScope *old_scope = current_scope; - CPPScope *old_global_scope = global_scope; - CPPPreprocessor *old_lexer = current_lexer; - CPPExpression *old_expr = current_expr; - - current_scope = new_current_scope; - global_scope = new_global_scope; - current_expr = nullptr; - current_lexer = pp; - yyparse(); - - CPPExpression *result = current_expr; - - current_scope = old_scope; - global_scope = old_global_scope; - current_lexer = old_lexer; - current_expr = old_expr; - - return result; -} - -CPPType * -parse_type(CPPPreprocessor *pp, CPPScope *new_current_scope, - CPPScope *new_global_scope) { - CPPScope *old_scope = current_scope; - CPPScope *old_global_scope = global_scope; - CPPPreprocessor *old_lexer = current_lexer; - CPPType *old_type = current_type; - - current_scope = new_current_scope; - global_scope = new_global_scope; - current_type = nullptr; - current_lexer = pp; - yyparse(); - - CPPType *result = current_type; - - current_scope = old_scope; - global_scope = old_global_scope; - current_lexer = old_lexer; - current_type = old_type; - - return result; -} - -static void -push_scope(CPPScope *new_scope) { - last_scopes.push_back(current_scope); - if (new_scope != nullptr) { - current_scope = new_scope; - } -} - -static void -pop_scope() { - assert(!last_scopes.empty()); - current_scope = last_scopes.back(); - last_scopes.pop_back(); -} - -static void -push_storage_class(int new_storage_class) { - last_storage_classes.push_back(current_storage_class); - current_storage_class = new_storage_class; -} - -static void -pop_storage_class() { - assert(!last_storage_classes.empty()); - current_storage_class = last_storage_classes.back(); - last_storage_classes.pop_back(); -} - -static void -push_struct(CPPStructType *new_struct) { - last_structs.push_back(current_struct); - current_struct = new_struct; -} - -static void -pop_struct() { - assert(!last_structs.empty()); - current_struct = last_structs.back(); - last_structs.pop_back(); -} - -%} - -/* This is a bison-specific declaration to enable recursive calls to - yyparse(). It changes the calling sequence to yylex(), passing - pointers to the current yylval and yylloc. Bison 2.7 introduces a - different syntax that will also pass the current yylloc to yyerror, - but we have to support Bison versions as old as 2.5 for now. */ -/*%define api.pure full*/ -%pure-parser -%locations - -%token REAL -%token INTEGER -%token CHAR_TOK -%token SIMPLE_STRING SIMPLE_IDENTIFIER -%token STRING_LITERAL CUSTOM_LITERAL -%token IDENTIFIER TYPENAME_IDENTIFIER TYPEPACK_IDENTIFIER SCOPING -%token TYPEDEFNAME - -%token ELLIPSIS -%token OROR -%token ANDAND -%token EQCOMPARE -%token NECOMPARE -%token LECOMPARE -%token GECOMPARE -%token SPACESHIP -%token LSHIFT -%token RSHIFT -%token POINTSAT_STAR -%token DOT_STAR -%token UNARY -%token UNARY_NOT -%token UNARY_NEGATE -%token UNARY_MINUS -%token UNARY_PLUS -%token UNARY_STAR -%token UNARY_REF -%token POINTSAT -%token SCOPE -%token PLUSPLUS -%token MINUSMINUS -%token TIMESEQUAL -%token DIVIDEEQUAL -%token MODEQUAL -%token PLUSEQUAL -%token MINUSEQUAL -%token OREQUAL -%token ANDEQUAL -%token XOREQUAL -%token LSHIFTEQUAL -%token RSHIFTEQUAL -%token ATTR_LEFT -%token ATTR_RIGHT - -%token KW_ALIGNAS -%token KW_ALIGNOF -%token KW_AUTO -%token KW_BEGIN_PUBLISH -%token KW_BLOCKING -%token KW_BOOL -%token KW_BUILTIN_VA_LIST -%token KW_CATCH -%token KW_CHAR -%token KW_CHAR8_T -%token KW_CHAR16_T -%token KW_CHAR32_T -%token KW_CLASS -%token KW_CONST -%token KW_CONSTEVAL -%token KW_CONSTEXPR -%token KW_CONSTINIT -%token KW_CONST_CAST -%token KW_DECLTYPE -%token KW_DEFAULT -%token KW_DELETE -%token KW_DOUBLE -%token KW_DYNAMIC_CAST -%token KW_ELSE -%token KW_END_PUBLISH -%token KW_ENUM -%token KW_EXTENSION -%token KW_EXTERN -%token KW_EXPLICIT -%token KW_EXPLICIT_LPAREN -%token KW_PUBLISHED -%token KW_FALSE -%token KW_FINAL -%token KW_FLOAT -%token KW_FRIEND -%token KW_FOR -%token KW_GOTO -%token KW_HAS_VIRTUAL_DESTRUCTOR -%token KW_IF -%token KW_INLINE -%token KW_INT -%token KW_IS_ABSTRACT -%token KW_IS_BASE_OF -%token KW_IS_CLASS -%token KW_IS_CONSTRUCTIBLE -%token KW_IS_CONVERTIBLE_TO -%token KW_IS_DESTRUCTIBLE -%token KW_IS_EMPTY -%token KW_IS_ENUM -%token KW_IS_FINAL -%token KW_IS_FUNDAMENTAL -%token KW_IS_POD -%token KW_IS_POLYMORPHIC -%token KW_IS_STANDARD_LAYOUT -%token KW_IS_TRIVIAL -%token KW_IS_TRIVIALLY_COPYABLE -%token KW_IS_UNION -%token KW_LONG -%token KW_MAKE_MAP_KEYS_SEQ -%token KW_MAKE_MAP_PROPERTY -%token KW_MAKE_PROPERTY -%token KW_MAKE_PROPERTY2 -%token KW_MAKE_SEQ -%token KW_MAKE_SEQ_PROPERTY -%token KW_MUTABLE -%token KW_NAMESPACE -%token KW_NEW -%token KW_NOEXCEPT -%token KW_NOEXCEPT_LPAREN -%token KW_NULLPTR -%token KW_OPERATOR -%token KW_OVERRIDE -%token KW_PRIVATE -%token KW_PROTECTED -%token KW_PUBLIC -%token KW_REGISTER -%token KW_REINTERPRET_CAST -%token KW_RESTRICT -%token KW_RETURN -%token KW_SHORT -%token KW_SIGNED -%token KW_SIZEOF -%token KW_STATIC -%token KW_STATIC_ASSERT -%token KW_STATIC_CAST -%token KW_STRUCT -%token KW_TEMPLATE -%token KW_THREAD_LOCAL -%token KW_THROW -%token KW_TRUE -%token KW_TRY -%token KW_TYPEDEF -%token KW_TYPEID -%token KW_TYPENAME -%token KW_UNDERLYING_TYPE -%token KW_UNION -%token KW_UNSIGNED -%token KW_USING -%token KW_VIRTUAL -%token KW_VOID -%token KW_VOLATILE -%token KW_WCHAR_T -%token KW_WHILE - -/* These special tokens are used to set the starting state of the - parser. The lexer places the appropriate one of these on the head - of the input stream. */ -%token START_CPP -%token START_CONST_EXPR -%token START_TYPE - -%type optional_attributes -%type attribute_specifiers -%type attribute_specifier -%type storage_class -%type constructor_prototype -%type function_prototype -%type function_post -%type function_operator -%type template_formal_parameter -%type template_formal_parameter_type -%type instance_identifier -%type instance_identifier_and_maybe_trailing_return_type -%type function_parameter_list -%type function_parameters -%type formal_parameter_list -%type formal_parameters -%type capture_list -%type capture -%type template_parameter_maybe_initialize -%type maybe_initialize -%type maybe_initialize_or_constructor_body -%type maybe_initialize_or_function_body -%type function_parameter -%type formal_parameter -%type not_paren_formal_parameter_identifier -%type formal_parameter_identifier -%type parameter_pack_identifier -%type not_paren_empty_instance_identifier -%type empty_instance_identifier -%type type type_pack -%type type_decl -%type var_type_decl -%type predefined_type -%type full_type -%type anonymous_struct -%type named_struct -%type enum -%type enum_keyword -%type struct_keyword -%type simple_type -%type simple_int_type -%type simple_float_type -%type simple_void_type -%type class_derivation_name -%type enum_element_type -%type maybe_trailing_return_type -%type maybe_comma_identifier -/*%type typedefname*/ -%type name -%type name_no_final -%type string_literal - -/* We need to treat KW_OPERATOR as a scopable keyword. */ -%type KW_OPERATOR - -%type optional_const_expr -%type optional_const_expr_comma -%type const_expr_comma -%type no_angle_bracket_const_expr -%type const_expr -%type const_operand -%type formal_const_expr -%type formal_const_operand - - -/* Precedence rules. */ - -%left IDENTIFIER TYPENAME_IDENTIFIER TYPEDEFNAME KW_ENUM ELLIPSIS KW_OPERATOR KW_TYPENAME KW_INT KW_SHORT KW_UNSIGNED KW_SIGNED KW_LONG KW_FLOAT KW_DOUBLE KW_CHAR KW_WCHAR_T KW_CHAR8_T KW_CHAR16_T KW_CHAR32_T KW_BOOL - -%left '{' ',' ';' - -%nonassoc KW_THROW -%right ':' -%right '=' -%right '?' -%left OROR -%left ANDAND -%left '|' -%left '^' -%left '&' -%left EQCOMPARE NECOMPARE -%left LECOMPARE GECOMPARE '<' '>' -%left SPACESHIP -%left LSHIFT RSHIFT -%left '+' '-' -%left '*' '/' '%' -%left POINTSAT_STAR DOT_STAR -%right UNARY PLUSPLUS MINUSMINUS '~' -%left POINTSAT '.' '(' '[' - -%right SCOPE -%nonassoc KW_NEW KW_DELETE KW_TRY KW_CATCH - -%% - -grammar: - START_CPP cpp - | START_CONST_EXPR const_expr -{ - current_expr = $2; -} - | START_TYPE full_type -{ - current_type = $2; -} - ; - -cpp: - empty - | cpp optional_attributes ';' -{ - if (!$2.is_empty()) { - current_scope->add_declaration(new CPPDeclaration(@2.file, $2), global_scope, current_lexer, @2); - } -} - | cpp optional_attributes -{ - current_attributes = $2; -} - declaration -{ - current_attributes = CPPAttributeList(); -} - ; - -constructor_inits: - constructor_init - | constructor_inits ',' constructor_init - ; - -constructor_init: - name '(' optional_const_expr_comma ')' -{ - delete $3; -} - | name '(' optional_const_expr_comma ')' ELLIPSIS -{ - delete $3; -} - | name '{' optional_const_expr_comma '}' -{ - delete $3; -} - ; - -/* This is principally for the syntax: extern "C" { ... }. - - We use storage_class instead of simply KW_EXTERN to avoid - shift/reduce conflicts with yacc's limited differentiation - ability. */ -extern_c: - storage_class '{' -{ - push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | - ($1 & CPPInstance::SC_c_binding)); -} - cpp '}' -{ - pop_storage_class(); -} - ; - -declaration: - type_like_declaration - | template_declaration - | extern_c - | namespace_declaration - | friend_declaration - | KW_TYPEDEF typedef_declaration - | KW_BEGIN_PUBLISH -{ - if (publish_nest_level != 0) { - yyerror("Unclosed __begin_publish", publish_loc); - publish_nest_level = 0; - current_scope->set_current_vis(V_public); - } - - publish_previous = current_scope->get_current_vis(); - publish_loc = @1; - publish_nest_level++; - current_scope->set_current_vis(V_published); -} - | KW_END_PUBLISH -{ - if (publish_nest_level != 1) { - yyerror("Unmatched __end_publish", @1); - } else { - current_scope->set_current_vis(publish_previous); - } - publish_nest_level = 0; -} - | KW_PUBLISHED ':' -{ - current_scope->set_current_vis(V_published); -} - | KW_PUBLIC ':' -{ - if (publish_nest_level > 0) { - current_scope->set_current_vis(V_published); - } else { - current_scope->set_current_vis(V_public); - } -} - | KW_PROTECTED ':' -{ - current_scope->set_current_vis(V_protected); -} - | KW_PRIVATE ':' -{ - current_scope->set_current_vis(V_private); -} - | KW_MAKE_PROPERTY '(' name ',' IDENTIFIER maybe_comma_identifier ')' ';' -{ - CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5); - } else { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - - if ($6 != nullptr) { - CPPDeclaration *setter = $6->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + $6->get_fully_scoped_name(), @6); - } else { - make_property->_set_function = setter->as_function_group(); - } - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5); - - } else { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *deleter = $9->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + $9->get_fully_scoped_name(), @9); - } else { - make_property->_del_function = deleter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); - length_getter = nullptr; - } - - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); - length_getter = nullptr; - } - - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - - CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); - } else { - make_property->_set_function = setter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); - length_getter = nullptr; - } - - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - - CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11); - } else { - make_property->_del_function = deleter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); - length_getter = nullptr; - } - - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - - CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11); - } else { - make_property->_del_function = deleter->as_function_group(); - } - - CPPDeclaration *inserter = $13->find_symbol(current_scope, global_scope, current_lexer); - if (inserter == nullptr || inserter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid append method: " + $13->get_fully_scoped_name(), @13); - } else { - make_property->_insert_function = inserter->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid item getter method: " + $5->get_fully_scoped_name(), @5); - - } else { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_mapping, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - - } else { - CPPMakeProperty *make_property; - make_property = new CPPMakeProperty($3, CPPMakeProperty::T_mapping, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER maybe_comma_identifier ')' ';' -{ - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - - } else { - CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_mapping, current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); - } else { - make_property->_set_function = setter->as_function_group(); - } - - if ($10 != nullptr) { - CPPDeclaration *deleter = $10->find_symbol(current_scope, global_scope, current_lexer); - if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid delete method: " + $10->get_fully_scoped_name(), @10); - } else { - make_property->_del_function = deleter->as_function_group(); - } - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_MAP_KEYS_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); - length_getter = nullptr; - } - - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - getter = nullptr; - } - - if (getter != nullptr && length_getter != nullptr) { - CPPMakeProperty *make_property = nullptr; - for (size_t i = 0; i < current_scope->_declarations.size(); ++i) { - make_property = current_scope->_declarations[i]->as_make_property(); - if (make_property != nullptr) { - if (make_property->get_fully_scoped_name() == $3->get_fully_scoped_name()) { - break; - } else { - make_property = nullptr; - } - } - } - if (make_property != nullptr) { - make_property->_get_key_function = getter->as_function_group(); - make_property->_length_function = length_getter->as_function_group(); - } else { - yyerror("reference to non-existent MAKE_MAP_PROPERTY: " + $3->get_fully_scoped_name(), @3); - } - } -} - | KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - - } else { - CPPMakeProperty *make_property; - make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal, - current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7); - - } else { - CPPMakeProperty *make_property; - make_property = new CPPMakeProperty($3, CPPMakeProperty::T_normal, - current_scope, @1.file); - make_property->_get_function = getter->as_function_group(); - - CPPDeclaration *hasser = $5->find_symbol(current_scope, global_scope, current_lexer); - if (hasser == nullptr || hasser->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid has/find method: " + $5->get_fully_scoped_name(), @5); - } else { - make_property->_has_function = hasser->as_function_group(); - } - - CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer); - if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9); - } else { - make_property->_set_function = setter->as_function_group(); - } - - CPPDeclaration *clearer = $11->find_symbol(current_scope, global_scope, current_lexer); - if (clearer == nullptr || clearer->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid clear method: " + $11->get_fully_scoped_name(), @11); - } else { - make_property->_clear_function = clearer->as_function_group(); - } - - current_scope->add_declaration(make_property, global_scope, current_lexer, @1); - } -} - | KW_MAKE_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' -{ - CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer); - if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5); - length_getter = nullptr; - } - - CPPDeclaration *element_getter = $7->find_symbol(current_scope, global_scope, current_lexer); - if (element_getter == nullptr || element_getter->get_subtype() != CPPDeclaration::ST_function_group) { - yyerror("reference to non-existent or invalid element method: " + $7->get_fully_scoped_name(), @5); - element_getter = nullptr; - } - - if (length_getter != nullptr && element_getter != nullptr) { - CPPMakeSeq *make_seq = new CPPMakeSeq($3, - length_getter->as_function_group(), - element_getter->as_function_group(), - current_scope, @1.file); - current_scope->add_declaration(make_seq, global_scope, current_lexer, @1); - } -} - | KW_STATIC_ASSERT '(' const_expr ',' string_literal ')' ';' -{ - CPPExpression::Result result = $3->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("static_assert requires a constant expression", @3); - } else if (!result.as_boolean()) { - stringstream str; - str << *$5; - yywarning("static_assert failed: " + str.str(), @3); - } -} - | KW_STATIC_ASSERT '(' const_expr ')' ';' -{ - // This alternative version of static_assert was introduced in C++17. - CPPExpression::Result result = $3->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("static_assert requires a constant expression", @3); - } else if (!result.as_boolean()) { - yywarning("static_assert failed", @3); - } -} - ; - -friend_declaration: - KW_FRIEND -{ - CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("temp"), - V_public); - push_scope(new_scope); -} - declaration -{ - delete current_scope; - pop_scope(); -} - ; - - -storage_class: - empty -{ - $$ = 0; -} - | KW_CONST storage_class -{ - // This isn't really a storage class, but it helps with parsing. - $$ = $2 | (int)CPPInstance::SC_const; -} - | KW_EXTERN storage_class -{ - $$ = $2 | (int)CPPInstance::SC_extern; -} - | KW_EXTERN SIMPLE_STRING storage_class -{ - $$ = $3 | (int)CPPInstance::SC_extern; - if ($2 == "C") { - $$ |= (int)CPPInstance::SC_c_binding; - } else if ($2 == "C++") { - $$ &= ~(int)CPPInstance::SC_c_binding; - } else { - yywarning("Ignoring unknown linkage type \"" + $2 + "\"", @2); - } -} - | KW_STATIC storage_class -{ - $$ = $2 | (int)CPPInstance::SC_static; -} - | KW_INLINE storage_class -{ - $$ = $2 | (int)CPPInstance::SC_inline; -} - | KW_VIRTUAL storage_class -{ - $$ = $2 | (int)CPPInstance::SC_virtual; -} - | KW_EXPLICIT storage_class -{ - $$ = $2 | (int)CPPInstance::SC_explicit; -} - | KW_EXPLICIT_LPAREN const_expr ')' storage_class -{ - CPPExpression::Result result = $2->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("explicit() requires a constant expression", @2); - } else if (result.as_boolean()) { - $$ = $4 | (int)CPPInstance::SC_explicit; - } -} - | KW_REGISTER storage_class -{ - $$ = $2 | (int)CPPInstance::SC_register; -} - | KW_VOLATILE storage_class -{ - $$ = $2 | (int)CPPInstance::SC_volatile; -} - | KW_MUTABLE storage_class -{ - $$ = $2 | (int)CPPInstance::SC_mutable; -} - | KW_CONSTEVAL storage_class -{ - $$ = $2 | (int)CPPInstance::SC_consteval; -} - | KW_CONSTEXPR storage_class -{ - $$ = $2 | (int)CPPInstance::SC_constexpr; -} - | KW_CONSTINIT storage_class -{ - $$ = $2 | (int)CPPInstance::SC_constinit; -} - | KW_BLOCKING storage_class -{ - $$ = $2 | (int)CPPInstance::SC_blocking; -} - | KW_EXTENSION storage_class -{ - $$ = $2 | (int)CPPInstance::SC_extension; -} - | KW_THREAD_LOCAL storage_class -{ - $$ = $2 | (int)CPPInstance::SC_thread_local; -} - ; - -optional_attributes: - empty -{ - $$ = CPPAttributeList(); -} - | ATTR_LEFT attribute_specifiers ATTR_RIGHT optional_attributes -{ - $$ = $2; - $$.add_attributes_from($4); -} - | ATTR_LEFT KW_USING name ':' attribute_specifiers ATTR_RIGHT optional_attributes -{ - $$ = $5; - for (CPPAttributeList::Attribute &attr : $$._attributes) { - attr._ident->prepend($3); - } - $$.add_attributes_from($7); -} - | KW_ALIGNAS '(' const_expr ')' optional_attributes -{ - $$ = $5; - $$.add_alignas($3->as_expression()); -} - | KW_ALIGNAS '(' type_decl ')' optional_attributes -{ - $$ = $5; - $$.add_alignas($3->as_type()); -} - ; - -attribute_specifiers: - attribute_specifier -{ - $$ = $1; -} - | attribute_specifier ',' attribute_specifiers -{ - $$ = $1; - $$.add_attributes_from($3); -} - ; - -attribute_specifier: - name -{ - $$ = CPPAttributeList(); - $$.add_attribute($1); -} - | name '(' formal_parameter_list ')' -{ - $$ = CPPAttributeList(); - $$.add_attribute($1); -} - ; - -type_like_declaration: - storage_class var_type_decl -{ - // We don't need to push/pop type, because we can't nest - // type_like_declaration. - if ($2->as_type_declaration()) { - current_type = $2->as_type_declaration()->_type; - } else { - current_type = $2->as_type(); - } - push_storage_class($1); -} - multiple_instance_identifiers -{ - pop_storage_class(); -} - - | storage_class type_decl ';' -{ - // We don't really care about the storage class here. In fact, it's - // not actually legal to define a class or struct using a particular - // storage class, but we require it just to help yacc out in its - // parsing. - - current_scope->add_declaration($2, global_scope, current_lexer, @2); -} - | storage_class constructor_prototype -{ - if ($2 != nullptr) { - // Push the scope so that the initializers can make use of things defined - // in the class body. - push_scope($2->get_scope(current_scope, global_scope)); - $2->_storage_class |= (current_storage_class | $1); - } -} - maybe_initialize_or_constructor_body -{ - if ($2 != nullptr) { - pop_scope(); - current_scope->add_declaration($2, global_scope, current_lexer, @2); - $2->set_initializer($4); - } -} - | storage_class function_prototype maybe_initialize_or_function_body -{ - if ($2 != nullptr) { - $2->_storage_class |= (current_storage_class | $1); - current_scope->add_declaration($2, global_scope, current_lexer, @2); - $2->set_initializer($3); - } -} - | using_declaration - - /* We don't need to include a rule for variables that point to - functions, because we get those from the function_prototype - definition. */ - ; - -multiple_instance_identifiers: - instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body -{ - if (current_storage_class & CPPInstance::SC_const) { - $1->add_modifier(IIT_const); - } - $1->add_attributes(current_attributes); - CPPInstance *inst = new CPPInstance(current_type, $1, - current_storage_class, - @1.file); - inst->set_initializer($2); - current_scope->add_declaration(inst, global_scope, current_lexer, @1); -} - | instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' multiple_instance_identifiers -{ - if (current_storage_class & CPPInstance::SC_const) { - $1->add_modifier(IIT_const); - } - $1->add_attributes(current_attributes); - CPPInstance *inst = new CPPInstance(current_type, $1, - current_storage_class, - @1.file); - inst->set_initializer($2); - current_scope->add_declaration(inst, global_scope, current_lexer, @1); -} - ; - - -typedef_declaration: - storage_class var_type_decl -{ - // We don't need to push/pop type, because we can't nest - // multiple_var_declarations. - if ($2->as_type_declaration()) { - current_type = $2->as_type_declaration()->_type; - } else { - current_type = $2->as_type(); - } - push_storage_class($1); -} - typedef_instance_identifiers -{ - pop_storage_class(); -} - | storage_class function_prototype maybe_initialize_or_function_body -{ - if ($2 != nullptr) { - CPPInstance *inst = $2->as_instance(); - if (inst != nullptr) { - inst->_storage_class |= (current_storage_class | $1); - current_scope->add_declaration(inst, global_scope, current_lexer, @2); - CPPTypedefType *typedef_type = new CPPTypedefType(inst->_type, inst->_ident, current_scope, inst->_attributes); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @2); - } - } -} - ; - -typedef_instance_identifiers: - instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body -{ - if (current_storage_class & CPPInstance::SC_const) { - $1->add_modifier(IIT_const); - } - $1->add_attributes(current_attributes); - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1); -} - | instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' typedef_instance_identifiers -{ - if (current_storage_class & CPPInstance::SC_const) { - $1->add_modifier(IIT_const); - } - $1->add_attributes(current_attributes); - CPPType *target_type = current_type; - CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file); - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1); -} - ; - -constructor_prototype: - -/* Functions with implicit return types, and constructors */ - IDENTIFIER '(' -{ - // Create a scope for this function. - CPPScope *scope = new CPPScope($1->get_scope(current_scope, global_scope), - $1->_names.back(), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} - function_parameter_list ')' function_post optional_attributes -{ - CPPScope *scope = $1->get_scope(current_scope, global_scope); - CPPType *type; - std::string simple_name = $1->get_simple_name(); - if (!simple_name.empty() && simple_name[0] == '~') { - // A destructor has no return type. - type = new CPPSimpleType(CPPSimpleType::T_void); - } - else if (scope != nullptr && simple_name == scope->get_simple_name()) { - // Neither does a constructor. - type = new CPPSimpleType(CPPSimpleType::T_void); - } - else { - // This isn't a constructor, so it has an implicit return type of - // int. - yywarning("function has no return type, assuming int", @1); - type = new CPPSimpleType(CPPSimpleType::T_int); - } - pop_scope(); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier($1); - ii->add_func_modifier($4, $6, nullptr, $7); - ii->add_attributes(current_attributes); - - $$ = new CPPInstance(type, ii, 0, @1.file); -} -/* This is a hack to support functions with the identifier enveloped by a - pair of parentheses. */ - | TYPENAME_IDENTIFIER '(' IDENTIFIER ')' '(' -{ - // Create a scope for this function. - CPPScope *scope = new CPPScope($3->get_scope(current_scope, global_scope), - $3->_names.back(), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} - function_parameter_list ')' function_post optional_attributes -{ - pop_scope(); - CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert(type != nullptr); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier($3); - ii->add_func_modifier($7, $9, nullptr, $10); - ii->add_attributes(current_attributes); - - $$ = new CPPInstance(type, ii, 0, @1.file); -} - | TYPENAME_IDENTIFIER '(' -{ - // Create a scope for this function. - CPPScope *scope = new CPPScope($1->get_scope(current_scope, global_scope), - $1->_names.back(), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} - function_parameter_list ')' function_post optional_attributes -{ - pop_scope(); - CPPType *type; - if ($1->get_simple_name() == current_scope->get_simple_name()) { - // This is a constructor, and has no return. - type = new CPPSimpleType(CPPSimpleType::T_void); - } else { - // This isn't a constructor, so it has an implicit return type of - // int. - type = new CPPSimpleType(CPPSimpleType::T_int); - } - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier($1); - ii->add_func_modifier($4, $6, nullptr, $7); - ii->add_attributes(current_attributes); - - $$ = new CPPInstance(type, ii, 0, @1.file); -} - ; - -function_prototype: - -/* Destructors */ - '~' name '(' -{ - push_scope($2->get_scope(current_scope, global_scope)); -} - function_parameter_list ')' function_post optional_attributes -{ - pop_scope(); - if ($2->is_scoped()) { - yyerror("Invalid destructor name: ~" + $2->get_fully_scoped_name(), @2); - } else { - CPPIdentifier *ident = - new CPPIdentifier("~" + $2->get_simple_name(), @2); - delete $2; - - CPPType *type; - type = new CPPSimpleType(CPPSimpleType::T_void); - - CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident); - ii->add_func_modifier($5, $7, nullptr, $8); - ii->add_attributes(current_attributes); - - $$ = new CPPInstance(type, ii, 0, @2.file); - } -} - -/* This is a special case: a function pointer declaration that looks - at first a lot like a constructor declaration. This is provided to - help yacc sort out the differences. It isn't an ideal solution, - because it doesn't catch a lot of subtle variants on this form--but - this will get at least the 99% most common uses. */ - - | TYPENAME_IDENTIFIER '(' '*' instance_identifier ')' '(' -{ - push_scope($4->get_scope(current_scope, global_scope)); -} - function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type -{ - pop_scope(); - CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert(type != nullptr); - - CPPInstanceIdentifier *ii = $4; - ii->add_modifier(IIT_pointer); - ii->add_func_modifier($8, $10, nullptr, $11); - ii->add_attributes(current_attributes); - $$ = new CPPInstance(type, ii, 0, @1.file); -} - | TYPENAME_IDENTIFIER '(' SCOPING '*' instance_identifier ')' '(' -{ - push_scope($5->get_scope(current_scope, global_scope)); -} - function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type -{ - pop_scope(); - CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert(type != nullptr); - - CPPInstanceIdentifier *ii = $5; - ii->add_scoped_pointer_modifier($3); - ii->add_func_modifier($9, $11, nullptr, $12); - ii->add_attributes(current_attributes); - $$ = new CPPInstance(type, ii, 0, @1.file); -} - -/* Typecast operators */ - | KW_OPERATOR type not_paren_formal_parameter_identifier '(' -{ - if ($1 != nullptr) { - push_scope($1->get_scope(current_scope, global_scope)); - } -} - function_parameter_list ')' function_post -{ - if ($1 != nullptr) { - pop_scope(); - } - - // We use formal_parameter_identifier, because that can match a type - // name with or without an identifier, but especially without, which - // is what follows the keyword "operator" in a typecast function. - // As an added bonus, the type of the formal_parameter will be the - // typecast type, i.e. the return type of the typecast function. - - // We give typecast operators the name "operator typecast ", - // where is a simple name of the type to be typecast. Use - // the method's return type to determine the full type description. - string name = "operator typecast " + $2->get_simple_name(); - CPPIdentifier *ident = $1; - if (ident == nullptr) { - ident = new CPPIdentifier(name, @2); - } else { - ident->add_name(name); - } - $$ = CPPInstance::make_typecast_function - (new CPPInstance($2, $3, 0, @3.file), ident, $6, $8); - $$->_attributes.add_attributes_from(current_attributes); -} - | KW_OPERATOR KW_CONST type not_paren_formal_parameter_identifier '(' -{ - if ($1 != nullptr) { - push_scope($1->get_scope(current_scope, global_scope)); - } -} - function_parameter_list ')' function_post -{ - if ($1 != nullptr) { - pop_scope(); - } - - CPPIdentifier *ident = $1; - if (ident == nullptr) { - ident = new CPPIdentifier("operator typecast", @4); - } else { - ident->add_name("operator typecast"); - } - $4->add_modifier(IIT_const); - $4->add_attributes(current_attributes); - $$ = CPPInstance::make_typecast_function - (new CPPInstance($3, $4, 0, @4.file), ident, $7, $9); -} - -/* Not actually a function prototype, but maybe a template - instantiation. Just included here (instead of somewhere else) to - avoid shift/reduce conflicts. */ - | IDENTIFIER -{ - CPPDeclaration *decl = - $1->find_symbol(current_scope, global_scope, current_lexer); - if (decl != nullptr) { - $$ = decl->as_instance(); - } else { - $$ = nullptr; - } -} - ; - -function_post: - empty -{ - $$ = 0; -} - | function_post KW_CONST -{ - $$ = $1 | (int)CPPFunctionType::F_const_method; -} - | function_post KW_VOLATILE -{ - $$ = $1 | (int)CPPFunctionType::F_volatile_method; -} - | function_post KW_NOEXCEPT -{ - $$ = $1 | (int)CPPFunctionType::F_noexcept; -} - | function_post KW_NOEXCEPT_LPAREN const_expr ')' -{ - CPPExpression::Result result = $3->evaluate(); - if (result._type == CPPExpression::RT_error) { - yywarning("noexcept() requires a constant expression", @3); - } else if (result.as_boolean()) { - $$ = $1 | (int)CPPFunctionType::F_noexcept; - } -} - | function_post KW_FINAL -{ - $$ = $1 | (int)CPPFunctionType::F_final; -} - | function_post KW_OVERRIDE -{ - $$ = $1 | (int)CPPFunctionType::F_override; -} - | function_post '&' -{ - $$ = $1 | (int)CPPFunctionType::F_lvalue_method; -} - | function_post ANDAND -{ - $$ = $1 | (int)CPPFunctionType::F_rvalue_method; -} - | function_post KW_MUTABLE -{ - // Used for lambdas, currently ignored. - $$ = $1; -} - | function_post KW_CONSTEXPR -{ - // Used for lambdas in C++17, currently ignored. - $$ = $1; -} - | function_post KW_THROW '(' ')' -{ - $$ = $1; -} - | function_post KW_THROW '(' name ')' -{ - $$ = $1; -} - | function_post KW_THROW '(' name ELLIPSIS ')' -{ - $$ = $1; -} - ; - -function_operator: - '!' -{ - $$ = "!"; -} - | '~' -{ - $$ = "~"; -} - | '*' -{ - $$ = "*"; -} - | '/' -{ - $$ = "/"; -} - | '%' -{ - $$ = "%"; -} - | '+' -{ - $$ = "+"; -} - | '-' -{ - $$ = "-"; -} - | '|' -{ - $$ = "|"; -} - | '&' -{ - $$ = "&"; -} - | '^' -{ - $$ = "^"; -} - | OROR -{ - $$ = "||"; -} - | ANDAND -{ - $$ = "&&"; -} - | EQCOMPARE -{ - $$ = "=="; -} - | NECOMPARE -{ - $$ = "!="; -} - | LECOMPARE -{ - $$ = "<="; -} - | GECOMPARE -{ - $$ = ">="; -} - | '<' -{ - $$ = "<"; -} - | '>' -{ - $$ = ">"; -} - | SPACESHIP -{ - $$ = "<=>"; -} - | LSHIFT -{ - $$ = "<<"; -} - | RSHIFT -{ - $$ = ">>"; -} - | '=' -{ - $$ = "="; -} - | ',' -{ - $$ = ","; -} - | PLUSPLUS -{ - $$ = "++"; -} - | MINUSMINUS -{ - $$ = "--"; -} - | TIMESEQUAL -{ - $$ = "*="; -} - | DIVIDEEQUAL -{ - $$ = "/="; -} - | MODEQUAL -{ - $$ = "%="; -} - | PLUSEQUAL -{ - $$ = "+="; -} - | MINUSEQUAL -{ - $$ = "-="; -} - | OREQUAL -{ - $$ = "|="; -} - | ANDEQUAL -{ - $$ = "&="; -} - | XOREQUAL -{ - $$ = "^="; -} - | LSHIFTEQUAL -{ - $$ = "<<="; -} - | RSHIFTEQUAL -{ - $$ = ">>="; -} - | POINTSAT -{ - $$ = "->"; -} - | '[' ']' -{ - $$ = "[]"; -} - | '(' ')' -{ - $$ = "()"; -} - | KW_NEW -{ - $$ = "new"; -} - | KW_DELETE -{ - $$ = "delete"; -} - ; - -more_template_declaration: - type_like_declaration - | template_declaration - | friend_declaration - ; - -template_declaration: - KW_EXTERN template_declaration - | KW_TEMPLATE -{ - push_scope(new CPPTemplateScope(current_scope)); -} - '<' template_formal_parameters '>' more_template_declaration -{ - pop_scope(); -} - | KW_TEMPLATE type_like_declaration - | KW_TEMPLATE friend_declaration - ; - -template_formal_parameters: - empty - | template_nonempty_formal_parameters - ; - -template_nonempty_formal_parameters: - template_formal_parameter -{ - CPPTemplateScope *ts = current_scope->as_template_scope(); - assert(ts != nullptr); - ts->add_template_parameter($1); -} - | template_nonempty_formal_parameters ',' template_formal_parameter -{ - CPPTemplateScope *ts = current_scope->as_template_scope(); - assert(ts != nullptr); - ts->add_template_parameter($3); -} - ; - -typename_keyword: - KW_CLASS - | KW_TYPENAME - ; - -template_formal_parameter: - typename_keyword -{ - $$ = CPPType::new_type(new CPPClassTemplateParameter(nullptr)); -} - | typename_keyword name -{ - $$ = CPPType::new_type(new CPPClassTemplateParameter($2)); -} - | typename_keyword name '=' full_type -{ - $$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4)); -} - | typename_keyword ELLIPSIS -{ - CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter(nullptr); - ctp->_packed = true; - $$ = CPPType::new_type(ctp); -} - | typename_keyword ELLIPSIS name -{ - CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($3); - ctp->_packed = true; - $$ = CPPType::new_type(ctp); -} - | template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize -{ - CPPInstance *inst = new CPPInstance($1, $2, 0, @2.file); - inst->set_initializer($3); - $$ = inst; -} - | KW_CONST template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize -{ - $3->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); - inst->set_initializer($4); - $$ = inst; -} - | template_formal_parameter_type parameter_pack_identifier -{ - CPPInstance *inst = new CPPInstance($1, $2, 0, @2.file); - $$ = inst; -} - | KW_CONST template_formal_parameter_type parameter_pack_identifier -{ - $3->add_modifier(IIT_const); - CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); - $$ = inst; -} - | KW_VOLATILE template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize -{ - $3->add_modifier(IIT_volatile); - CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); - inst->set_initializer($4); - $$ = inst; -} - | KW_VOLATILE template_formal_parameter_type parameter_pack_identifier -{ - $3->add_modifier(IIT_volatile); - CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); - $$ = inst; -} - ; - -template_formal_parameter_type: - simple_type -{ - $$ = CPPType::new_type($1); -} - | IDENTIFIER -{ - yywarning("Not a type: " + $1->get_fully_scoped_name(), @1); - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); -} - | TYPENAME_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); - if ($$ == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert($$ != nullptr); -} - | TYPEPACK_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); - if ($$ == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert($$ != nullptr); -} - ; - - -instance_identifier: - name_no_final optional_attributes -{ - $$ = new CPPInstanceIdentifier($1, $2); -} - | KW_OPERATOR function_operator optional_attributes -{ - // For an operator function. We implement this simply by building a - // ficticious name for the function; in other respects it's just - // like a regular function. - CPPIdentifier *ident = $1; - if (ident == nullptr) { - ident = new CPPIdentifier("operator "+$2, @2); - } else { - ident->_names.push_back("operator "+$2); - } - - $$ = new CPPInstanceIdentifier(ident, $3); -} - | KW_OPERATOR SIMPLE_STRING IDENTIFIER optional_attributes -{ - // A C++11 literal operator. - if (!$2.empty()) { - yyerror("expected empty string", @2); - } - CPPIdentifier *ident = $1; - if (ident == nullptr) { - ident = new CPPIdentifier("operator \"\" "+$3->get_simple_name(), @3); - } else { - ident->_names.push_back("operator \"\" "+$3->get_simple_name()); - } - - $$ = new CPPInstanceIdentifier(ident, $4); -} - | KW_CONST instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_const); -} - | KW_VOLATILE instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_volatile); -} - | '*' optional_attributes instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_pointer, $2); -} - | '&' optional_attributes instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_reference, $2); -} - | ANDAND optional_attributes instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_rvalue_reference, $2); -} - | SCOPING '*' optional_attributes instance_identifier %prec UNARY -{ - $$ = $4; - $$->add_scoped_pointer_modifier($1, $3); -} - | instance_identifier '[' optional_const_expr ']' optional_attributes -{ - $$ = $1; - $$->add_array_modifier($3, $5); -} - | '(' instance_identifier ')' -{ - $$ = $2; - $$->add_modifier(IIT_paren); -} - | instance_identifier '(' -{ - // Create a scope for this function (in case it is a function) - CPPScope *scope = new CPPScope($1->get_scope(current_scope, global_scope), - CPPNameComponent(""), V_private); - - // It still needs to be able to pick up any template arguments, if this is - // a definition for a method template. Add a fake "using" declaration to - // accomplish this. - scope->_using.insert(current_scope); - - push_scope(scope); -} - formal_parameter_list ')' function_post optional_attributes -{ - pop_scope(); - $$ = $1; - if ($4->is_parameter_expr() && $6 == 0) { - // Oops, this must have been an instance declaration with a - // parameter list, not a function prototype. - $$->add_initializer_modifier($4); - } - else { - // This was (probably) a function prototype. - $$->add_func_modifier($4, $6, nullptr, $7); - } -} - ; - - -instance_identifier_and_maybe_trailing_return_type: - instance_identifier maybe_trailing_return_type -{ - // This is handled a bit awkwardly right now. Ideally it'd be wrapped - // up in the instance_identifier rule, but then more needs to happen in - // order to avoid shift/reduce conflicts. - if ($2 != nullptr) { - $1->add_trailing_return_type($2); - } - $$ = $1; -} - | instance_identifier ':' const_expr -{ - // Bitfield definition. - $1->_bit_width = $3; - $$ = $1; -} - ; - - -maybe_trailing_return_type: - empty -{ - $$ = nullptr; -} - | POINTSAT predefined_type empty_instance_identifier -{ - $$ = $3->unroll_type($2); -} - | POINTSAT KW_CONST predefined_type empty_instance_identifier -{ - $4->add_modifier(IIT_const); - $$ = $4->unroll_type($3); -} - ; - - -maybe_comma_identifier: - empty -{ - $$ = nullptr; -} - | ',' IDENTIFIER -{ - $$ = $2; -} - ; - - -function_parameter_list: - empty -{ - $$ = new CPPParameterList; -} - | ELLIPSIS -{ - $$ = new CPPParameterList; - $$->_includes_ellipsis = true; -} - | function_parameters -{ - $$ = $1; -} - | function_parameters ',' ELLIPSIS -{ - $$ = $1; - $$->_includes_ellipsis = true; -} - | function_parameters ELLIPSIS -{ - $$ = $1; - $$->_includes_ellipsis = true; -} - ; - -function_parameters: - function_parameter -{ - $$ = new CPPParameterList; - $$->_parameters.push_back($1); -} - | function_parameters ',' function_parameter -{ - $$ = $1; - $$->_parameters.push_back($3); -} - ; - -formal_parameter_list: - empty -{ - $$ = new CPPParameterList; -} - | ELLIPSIS -{ - $$ = new CPPParameterList; - $$->_includes_ellipsis = true; -} - | formal_parameters -{ - $$ = $1; -} - | formal_parameters ',' ELLIPSIS -{ - $$ = $1; - $$->_includes_ellipsis = true; -} - | formal_parameters ELLIPSIS -{ - $$ = $1; - $$->_includes_ellipsis = true; -} - ; - -formal_parameters: - formal_parameter -{ - $$ = new CPPParameterList; - $$->_parameters.push_back($1); -} - | formal_parameters ',' formal_parameter -{ - $$ = $1; - $$->_parameters.push_back($3); -} - ; - -template_parameter_maybe_initialize: - empty -{ - $$ = nullptr; -} - | '=' no_angle_bracket_const_expr -{ - $$ = $2; -} - ; - -maybe_initialize: - empty -{ - $$ = nullptr; -} - | '=' const_expr -{ - $$ = $2; -} - ; - -maybe_initialize_or_constructor_body: - ';' -{ - $$ = nullptr; -} - | '{' code '}' -{ - $$ = nullptr; -} - | ':' constructor_inits '{' code '}' -{ - $$ = nullptr; -} - | '=' KW_DEFAULT ';' -{ - $$ = new CPPExpression(CPPExpression::get_default()); -} - | '=' KW_DELETE ';' -{ - $$ = new CPPExpression(CPPExpression::get_delete()); -} - ; - -maybe_initialize_or_function_body: - ';' -{ - $$ = nullptr; -} - | '{' code '}' -{ - $$ = nullptr; -} - | '=' const_expr ';' -{ - $$ = $2; -} - | '=' KW_DEFAULT ';' -{ - $$ = new CPPExpression(CPPExpression::get_default()); -} - | '=' KW_DELETE ';' -{ - $$ = new CPPExpression(CPPExpression::get_delete()); -} - | '=' '{' structure_init '}' -{ - $$ = nullptr; -} - ; - -structure_init: - empty - | structure_init_body - | structure_init_body ',' - ; - -structure_init_body: - const_expr -{ -} - | '{' structure_init '}' - | structure_init_body ',' const_expr - | structure_init_body ',' '{' structure_init '}' - ; - -function_parameter: - optional_attributes storage_class type formal_parameter_identifier maybe_initialize -{ - if ($2 & CPPInstance::SC_const) { - $4->add_modifier(IIT_const); - } - if ($2 & CPPInstance::SC_volatile) { - $4->add_modifier(IIT_volatile); - } - $4->add_attributes($1); - $$ = new CPPInstance($3, $4, 0, @4.file); - $$->set_initializer($5); -} - | optional_attributes storage_class type_pack parameter_pack_identifier maybe_initialize -{ - if ($2 & CPPInstance::SC_const) { - $4->add_modifier(IIT_const); - } - if ($2 & CPPInstance::SC_volatile) { - $4->add_modifier(IIT_volatile); - } - $4->add_attributes($1); - $$ = new CPPInstance($3, $4, 0, @4.file); - $$->set_initializer($5); -} - ; - -/* A "formal parameter" is like a function parameter, except that it parses - * instance declarations (that look like functions declaration) as well, and - * as such accepts constexpr parameters. - */ -formal_parameter: - function_parameter -{ - $$ = $1; -} - | formal_const_expr -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_parameter)); - $$ = new CPPInstance(type, "expr"); - $$->set_initializer($1); -} - ; - -not_paren_formal_parameter_identifier: - empty -{ - $$ = new CPPInstanceIdentifier(nullptr); -} - | name_no_final optional_attributes -{ - $$ = new CPPInstanceIdentifier($1, $2); -} - | KW_CONST not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_const); -} - | KW_VOLATILE not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_volatile); -} - | KW_RESTRICT not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_restrict); -} - | '*' optional_attributes not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_pointer, $2); -} - | '&' optional_attributes not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_reference, $2); -} - | ANDAND optional_attributes not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_rvalue_reference, $2); -} - | SCOPING '*' optional_attributes not_paren_formal_parameter_identifier %prec UNARY -{ - $$ = $4; - $$->add_scoped_pointer_modifier($1, $3); -} - | not_paren_formal_parameter_identifier '[' optional_const_expr ']' optional_attributes -{ - $$ = $1; - $$->add_array_modifier($3, $5); -} - ; - -formal_parameter_identifier: - empty -{ - $$ = new CPPInstanceIdentifier(nullptr); -} - | name_no_final optional_attributes -{ - $$ = new CPPInstanceIdentifier($1, $2); -} - | KW_CONST formal_parameter_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_const); -} - | KW_VOLATILE formal_parameter_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_volatile); -} - | KW_RESTRICT formal_parameter_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_restrict); -} - | '*' optional_attributes formal_parameter_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_pointer, $2); -} - | '&' optional_attributes formal_parameter_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_reference, $2); -} - | ANDAND optional_attributes formal_parameter_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_rvalue_reference, $2); -} - | SCOPING '*' optional_attributes formal_parameter_identifier %prec UNARY -{ - $$ = $4; - $$->add_scoped_pointer_modifier($1, $3); -} - | formal_parameter_identifier '[' optional_const_expr ']' optional_attributes -{ - $$ = $1; - $$->add_array_modifier($3, $5); -} - | '(' formal_parameter_identifier ')' '(' function_parameter_list ')' function_post optional_attributes -{ - $$ = $2; - $$->add_modifier(IIT_paren); - $$->add_func_modifier($5, $7, nullptr, $8); -} - | '(' formal_parameter_identifier ')' -{ - $$ = $2; - $$->add_modifier(IIT_paren); -} - ; - -parameter_pack_identifier: - ELLIPSIS -{ - $$ = new CPPInstanceIdentifier(nullptr); - $$->_packed = true; -} - | ELLIPSIS name optional_attributes -{ - $$ = new CPPInstanceIdentifier($2, $3); - $$->_packed = true; -} - | KW_CONST parameter_pack_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_const); -} - | KW_VOLATILE parameter_pack_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_volatile); -} - | KW_RESTRICT parameter_pack_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_restrict); -} - | '*' optional_attributes parameter_pack_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_pointer, $2); -} - | '&' optional_attributes parameter_pack_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_reference, $2); -} - | ANDAND optional_attributes parameter_pack_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_rvalue_reference, $2); -} - | SCOPING '*' optional_attributes parameter_pack_identifier %prec UNARY -{ - $$ = $4; - $$->add_scoped_pointer_modifier($1, $3); -} - | parameter_pack_identifier '[' optional_const_expr ']' optional_attributes -{ - $$ = $1; - $$->add_array_modifier($3, $5); -} - | '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post optional_attributes -{ - $$ = $2; - $$->add_modifier(IIT_paren); - $$->add_func_modifier($5, $7, nullptr, $8); -} - | '(' parameter_pack_identifier ')' -{ - $$ = $2; - $$->add_modifier(IIT_paren); -} - ; - -not_paren_empty_instance_identifier: - empty -{ - $$ = new CPPInstanceIdentifier(nullptr); -} - | ELLIPSIS -{ - $$ = new CPPInstanceIdentifier(nullptr); - $$->_packed = true; -} - | ELLIPSIS name optional_attributes -{ - $$ = new CPPInstanceIdentifier($2, $3); - $$->_packed = true; -} - | KW_CONST not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_const); -} - | KW_VOLATILE not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_volatile); -} - | KW_RESTRICT not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_restrict); -} - | '*' optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_pointer, $2); -} - | '&' optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_reference, $2); -} - | ANDAND optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_rvalue_reference, $2); -} - | SCOPING '*' optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $4; - $$->add_scoped_pointer_modifier($1, $3); -} - | not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes -{ - $$ = $1; - $$->add_array_modifier($3, $5); -} - ; - -empty_instance_identifier: - empty -{ - $$ = new CPPInstanceIdentifier(nullptr); -} - | ELLIPSIS -{ - $$ = new CPPInstanceIdentifier(nullptr); - $$->_packed = true; -} - | ELLIPSIS name optional_attributes -{ - $$ = new CPPInstanceIdentifier($2, $3); - $$->_packed = true; -} - | KW_CONST empty_instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_const); -} - | KW_VOLATILE empty_instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_volatile); -} - | KW_RESTRICT empty_instance_identifier %prec UNARY -{ - $$ = $2; - $$->add_modifier(IIT_restrict); -} - | '*' optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_pointer, $2); -} - | '&' optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_reference, $2); -} - | ANDAND optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $3; - $$->add_modifier(IIT_rvalue_reference, $2); -} - | SCOPING '*' optional_attributes not_paren_empty_instance_identifier %prec UNARY -{ - $$ = $4; - $$->add_scoped_pointer_modifier($1, $3); -} - | not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes -{ - $$ = $1; - $$->add_array_modifier($3, $5); -} - | '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type -{ - $$ = new CPPInstanceIdentifier(nullptr); - $$->add_modifier(IIT_paren); - $$->add_func_modifier($2, $4, $6, $5); -} - | '(' '*' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type -{ - $$ = $4; - $$->add_modifier(IIT_pointer, $3); - $$->add_modifier(IIT_paren); - $$->add_func_modifier($7, $9, $11, $10); -} - | '(' '&' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type -{ - $$ = $4; - $$->add_modifier(IIT_reference, $3); - $$->add_modifier(IIT_paren); - $$->add_func_modifier($7, $9, $11, $10); -} - | '(' ANDAND optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type -{ - $$ = $4; - $$->add_modifier(IIT_rvalue_reference, $3); - $$->add_modifier(IIT_paren); - $$->add_func_modifier($7, $9, $11, $10); -} - ; - -type: - simple_type -{ - $$ = CPPType::new_type($1); -} - | TYPENAME_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); - if ($$ == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert($$ != nullptr); -} - | KW_TYPENAME name -{ - $$ = CPPType::new_type(new CPPTBDType($2)); -} - | anonymous_struct -{ - $$ = CPPType::new_type($1); -} - | named_struct -{ - $$ = CPPType::new_type($1); -} - | enum -{ - $$ = CPPType::new_type($1); -} - | struct_keyword optional_attributes name -{ - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | enum_keyword optional_attributes name_no_final ':' enum_element_type -{ - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | KW_DECLTYPE '(' const_expr ')' -{ - $$ = $3->determine_type(); - if ($$ == nullptr) { - stringstream str; - str << *$3; - yyerror("could not determine type of " + str.str(), @3); - } -} - | KW_DECLTYPE '(' KW_AUTO ')' -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - | KW_UNDERLYING_TYPE '(' full_type ')' -{ - CPPEnumType *enum_type = $3->as_enum_type(); - if (enum_type == nullptr) { - yyerror("an enumeration type is required", @3); - $$ = $3; - } else { - $$ = enum_type->get_underlying_type(); - } -} - | KW_AUTO -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - | KW_BUILTIN_VA_LIST -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); -} - ; - -type_pack: - TYPEPACK_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); - if ($$ == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert($$ != nullptr); -} - ; - -type_decl: - simple_type -{ - $$ = CPPType::new_type($1); -} - | TYPENAME_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); - if ($$ == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert($$ != nullptr); -} - | KW_TYPENAME name -{ - $$ = CPPType::new_type(new CPPTBDType($2)); -} - | anonymous_struct -{ - $$ = CPPType::new_type($1); -} - | named_struct -{ - $$ = new CPPTypeDeclaration(CPPType::new_type($1)); -} - | enum -{ - $$ = new CPPTypeDeclaration(CPPType::new_type($1)); -} - | struct_keyword optional_attributes name -{ - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | enum_keyword optional_attributes name_no_final ':' enum_element_type -{ - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | enum_keyword optional_attributes name -{ - yywarning(string("C++ does not permit forward declaration of untyped enum ") + $3->get_fully_scoped_name(), @1); - - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | KW_DECLTYPE '(' const_expr ')' -{ - $$ = $3->determine_type(); - if ($$ == nullptr) { - stringstream str; - str << *$3; - yyerror("could not determine type of " + str.str(), @3); - } -} - | KW_DECLTYPE '(' KW_AUTO ')' -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - | KW_UNDERLYING_TYPE '(' full_type ')' -{ - CPPEnumType *enum_type = $3->as_enum_type(); - if (enum_type == nullptr) { - yyerror("an enumeration type is required", @3); - $$ = $3; - } else { - $$ = enum_type->get_underlying_type(); - } -} - | KW_AUTO -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - | KW_BUILTIN_VA_LIST -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); -} - ; - -predefined_type: - simple_type -{ - $$ = CPPType::new_type($1); -} - | TYPENAME_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); - if ($$ == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert($$ != nullptr); -} - | KW_TYPENAME name -{ - $$ = CPPType::new_type(new CPPTBDType($2)); -} - | struct_keyword optional_attributes name -{ - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | enum_keyword optional_attributes name -{ - CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer); - if (type != nullptr) { - $$ = type; - } else { - CPPExtensionType *et = - CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file, $2)) - ->as_extension_type(); - CPPScope *scope = $3->get_scope(current_scope, global_scope); - if (scope != nullptr) { - scope->define_extension_type(et); - } - $$ = et; - } -} - | KW_DECLTYPE '(' const_expr ')' -{ - $$ = $3->determine_type(); - if ($$ == nullptr) { - stringstream str; - str << *$3; - yyerror("could not determine type of " + str.str(), @3); - } -} - | KW_UNDERLYING_TYPE '(' full_type ')' -{ - CPPEnumType *enum_type = $3->as_enum_type(); - if (enum_type == nullptr) { - yyerror("an enumeration type is required", @3); - $$ = $3; - } else { - $$ = enum_type->get_underlying_type(); - } -} - | KW_AUTO -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); -} - | KW_BUILTIN_VA_LIST -{ - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); -} - ; - -var_type_decl: - type_decl -{ - $$ = $1; -} - | IDENTIFIER -{ - yyerror(string("unknown type '") + $1->get_fully_scoped_name() + "'", @1); - - $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); -} - -full_type: - type empty_instance_identifier -{ - $$ = $2->unroll_type($1); -} - | KW_CONST type empty_instance_identifier -{ - $3->add_modifier(IIT_const); - $$ = $3->unroll_type($2); -} - | type_pack empty_instance_identifier -{ - $$ = $2->unroll_type($1); -} - | KW_CONST type_pack empty_instance_identifier -{ - $3->add_modifier(IIT_const); - $$ = $3->unroll_type($2); -} - ; - -anonymous_struct: - struct_keyword optional_attributes '{' -{ - CPPVisibility starting_vis = - ($1 == CPPExtensionType::T_class) ? V_private : V_public; - - CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"), - starting_vis); - CPPStructType *st = new CPPStructType($1, nullptr, current_scope, - new_scope, @1.file, $2); - new_scope->set_struct_type(st); - - push_scope(new_scope); - push_struct(st); -} - cpp '}' -{ - $$ = current_struct; - current_struct->_incomplete = false; - pop_struct(); - pop_scope(); -} - ; - -named_struct: - struct_keyword optional_attributes name_no_final -{ - CPPVisibility starting_vis = - ($1 == CPPExtensionType::T_class) ? V_private : V_public; - - CPPScope *scope = $3->get_scope(current_scope, global_scope, current_lexer); - if (scope == nullptr) { - scope = current_scope; - } - CPPScope *new_scope = new CPPScope(scope, $3->_names.back(), - starting_vis); - - CPPStructType *st = new CPPStructType($1, $3, current_scope, - new_scope, @1.file, $2); - new_scope->set_struct_type(st); - current_scope->define_extension_type(st); - - push_scope(new_scope); - push_struct(st); -} - maybe_final maybe_class_derivation '{' cpp '}' -{ - $$ = current_struct; - current_struct->_incomplete = false; - pop_struct(); - pop_scope(); -} - ; - -maybe_final: - empty - | KW_FINAL -{ - current_struct->_final = true; -} - ; - -maybe_class_derivation: - empty - | class_derivation - ; - -class_derivation: - ':' base_specification - | class_derivation ',' base_specification - ; - -base_specification: - class_derivation_name -{ - current_struct->append_derivation($1, V_unknown, false); -} - | KW_PUBLIC class_derivation_name -{ - current_struct->append_derivation($2, V_public, false); -} - | KW_PROTECTED class_derivation_name -{ - current_struct->append_derivation($2, V_protected, false); -} - | KW_PRIVATE class_derivation_name -{ - current_struct->append_derivation($2, V_private, false); -} - | KW_VIRTUAL KW_PUBLIC class_derivation_name -{ - current_struct->append_derivation($3, V_public, true); -} - | KW_VIRTUAL KW_PROTECTED class_derivation_name -{ - current_struct->append_derivation($3, V_protected, true); -} - | KW_VIRTUAL KW_PRIVATE class_derivation_name -{ - current_struct->append_derivation($3, V_private, true); -} - | KW_PUBLIC KW_VIRTUAL class_derivation_name -{ - current_struct->append_derivation($3, V_public, true); -} - | KW_PROTECTED KW_VIRTUAL class_derivation_name -{ - current_struct->append_derivation($3, V_protected, true); -} - | KW_PRIVATE KW_VIRTUAL class_derivation_name -{ - current_struct->append_derivation($3, V_private, true); -} - ; - -enum: - enum_decl -{ - if (current_enum->_scope != nullptr) { - push_scope(current_enum->_scope); - } -} - '{' enum_body '}' -{ - if (current_enum->_scope != nullptr) { - pop_scope(); - } - $$ = current_enum; - current_enum = nullptr; -} - ; - -enum_decl: - enum_keyword optional_attributes ':' enum_element_type -{ - current_enum = new CPPEnumType($1, nullptr, $4, current_scope, nullptr, @1.file, $2); -} - | enum_keyword optional_attributes -{ - current_enum = new CPPEnumType($1, nullptr, current_scope, nullptr, @1.file, $2); -} - | enum_keyword optional_attributes name_no_final ':' enum_element_type -{ - CPPScope *new_scope = new CPPScope(current_scope, $3->_names.back(), V_public); - current_enum = new CPPEnumType($1, $3, $5, current_scope, new_scope, @1.file, $2); -} - | enum_keyword optional_attributes name_no_final -{ - CPPScope *new_scope = new CPPScope(current_scope, $3->_names.back(), V_public); - current_enum = new CPPEnumType($1, $3, current_scope, new_scope, @1.file, $2); -} - ; - -enum_element_type: - simple_int_type -{ - $$ = CPPType::new_type($1); -} - | TYPENAME_IDENTIFIER -{ - $$ = $1->find_type(current_scope, global_scope, false, current_lexer); -} - ; - -enum_body_trailing_comma: - empty - | enum_body_trailing_comma name optional_attributes ',' -{ - assert(current_enum != nullptr); - current_enum->add_element($2->get_simple_name(), nullptr, current_lexer, @2, $3); -} - | enum_body_trailing_comma name optional_attributes '=' const_expr ',' -{ - assert(current_enum != nullptr); - current_enum->add_element($2->get_simple_name(), $5, current_lexer, @2, $3); -}; - -enum_body: - enum_body_trailing_comma - | enum_body_trailing_comma name optional_attributes -{ - assert(current_enum != nullptr); - current_enum->add_element($2->get_simple_name(), nullptr, current_lexer, @2, $3); -} - | enum_body_trailing_comma name optional_attributes '=' const_expr -{ - assert(current_enum != nullptr); - current_enum->add_element($2->get_simple_name(), $5, current_lexer, @2, $3); -} - ; - -enum_keyword: - KW_ENUM -{ - $$ = CPPExtensionType::T_enum; -} - | KW_ENUM KW_CLASS -{ - $$ = CPPExtensionType::T_enum_class; -} - | KW_ENUM KW_STRUCT -{ - $$ = CPPExtensionType::T_enum_struct; -} - ; - -struct_keyword: - KW_CLASS -{ - $$ = CPPExtensionType::T_class; -} - | KW_STRUCT -{ - $$ = CPPExtensionType::T_struct; -} - | KW_UNION -{ - $$ = CPPExtensionType::T_union; -} - ; - -namespace_declaration: - KW_NAMESPACE optional_attributes name '{' -{ - CPPScope *scope = $3->find_scope(current_scope, global_scope, current_lexer); - if (scope == nullptr) { - // This must be a new namespace declaration. - CPPScope *parent_scope = - $3->get_scope(current_scope, global_scope, current_lexer); - if (parent_scope == nullptr) { - parent_scope = current_scope; - } - scope = new CPPScope(parent_scope, $3->_names.back(), V_public); - } - - CPPNamespace *nspace = new CPPNamespace($3, scope, @1.file, $2); - current_scope->add_declaration(nspace, global_scope, current_lexer, @1); - current_scope->define_namespace(nspace); - push_scope(scope); -} - cpp '}' -{ - pop_scope(); -} - | KW_INLINE KW_NAMESPACE name '{' -{ - CPPScope *scope = $3->find_scope(current_scope, global_scope, current_lexer); - if (scope == nullptr) { - // This must be a new namespace declaration. - CPPScope *parent_scope = - $3->get_scope(current_scope, global_scope, current_lexer); - if (parent_scope == nullptr) { - parent_scope = current_scope; - } - scope = new CPPScope(parent_scope, $3->_names.back(), V_public); - } - - CPPNamespace *nspace = new CPPNamespace($3, scope, @2.file); - nspace->_is_inline = true; - current_scope->add_declaration(nspace, global_scope, current_lexer, @2); - current_scope->define_namespace(nspace); - push_scope(scope); -} - cpp '}' -{ - pop_scope(); -} - | KW_NAMESPACE '{' cpp '}' - | KW_INLINE KW_NAMESPACE '{' cpp '}' - ; - -using_declaration: - KW_USING name ';' -{ - CPPUsing *using_decl = new CPPUsing($2, false, @1.file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, @1); - current_scope->add_using(using_decl, global_scope, current_lexer); -} - | KW_USING name optional_attributes '=' full_type ';' -{ - // This is really just an alternative way to declare a typedef. - CPPTypedefType *typedef_type = new CPPTypedefType($5, $2, current_scope, $3); - typedef_type->_using = true; - current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1); -} - | KW_USING KW_NAMESPACE name ';' -{ - CPPUsing *using_decl = new CPPUsing($3, true, @1.file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, @1); - current_scope->add_using(using_decl, global_scope, current_lexer); -} - | KW_USING KW_ENUM name ';' -{ - CPPUsing *using_decl = new CPPUsing($3, false, @1.file); - current_scope->add_declaration(using_decl, global_scope, current_lexer, @1); - current_scope->add_using(using_decl, global_scope, current_lexer); -} - ; - -simple_type: - simple_int_type - | simple_float_type - | simple_void_type - ; - -simple_int_type: - KW_BOOL -{ - $$ = new CPPSimpleType(CPPSimpleType::T_bool); -} - | KW_CHAR -{ - $$ = new CPPSimpleType(CPPSimpleType::T_char); -} - | KW_WCHAR_T -{ - $$ = new CPPSimpleType(CPPSimpleType::T_wchar_t); -} - | KW_CHAR8_T -{ - $$ = new CPPSimpleType(CPPSimpleType::T_char8_t); -} - | KW_CHAR16_T -{ - $$ = new CPPSimpleType(CPPSimpleType::T_char16_t); -} - | KW_CHAR32_T -{ - $$ = new CPPSimpleType(CPPSimpleType::T_char32_t); -} - | KW_SHORT -{ - $$ = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_short); -} - | KW_LONG -{ - $$ = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_long); -} - | KW_UNSIGNED -{ - $$ = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_unsigned); -} - | KW_SIGNED -{ - $$ = new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_signed); -} - | KW_INT -{ - $$ = new CPPSimpleType(CPPSimpleType::T_int); -} - | KW_SHORT simple_int_type -{ - $$ = $2; - $$->_flags |= CPPSimpleType::F_short; -} - | KW_LONG simple_int_type -{ - $$ = $2; - if ($$->_flags & CPPSimpleType::F_long) { - $$->_flags |= CPPSimpleType::F_longlong; - } else { - $$->_flags |= CPPSimpleType::F_long; - } -} - | KW_UNSIGNED simple_int_type -{ - $$ = $2; - $$->_flags |= CPPSimpleType::F_unsigned; -} - | KW_SIGNED simple_int_type -{ - $$ = $2; - $$->_flags |= CPPSimpleType::F_signed; -} - ; - -simple_float_type: - KW_FLOAT -{ - $$ = new CPPSimpleType(CPPSimpleType::T_float); -} - | KW_DOUBLE -{ - $$ = new CPPSimpleType(CPPSimpleType::T_double); -} - | KW_LONG KW_DOUBLE -{ - $$ = new CPPSimpleType(CPPSimpleType::T_double, - CPPSimpleType::F_long); -} - ; - -simple_void_type: - KW_VOID -{ - $$ = new CPPSimpleType(CPPSimpleType::T_void); -} - ; - -/* We don't care what the code is. We just want to be sure we match - up opening and closing braces properly. For anything else, we'll - accept just token salad. */ -code: -{ - current_lexer->_resolve_identifiers = false; -} - code_block -{ - current_lexer->_resolve_identifiers = true; -} - ; - -code_block: - empty - | code_block element - ; - -element: - REAL - | INTEGER - | SIMPLE_STRING - | STRING_LITERAL - | CUSTOM_LITERAL - | CHAR_TOK - | IDENTIFIER - | TYPENAME_IDENTIFIER - | TYPEPACK_IDENTIFIER - | SCOPING - | SIMPLE_IDENTIFIER - | ELLIPSIS | OROR | ANDAND - | EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE | SPACESHIP - | LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT - | SCOPE | PLUSPLUS | MINUSMINUS - | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL - | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL - | ATTR_LEFT | ATTR_RIGHT - | KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_BUILTIN_VA_LIST - | KW_CATCH | KW_CHAR | KW_CHAR8_T | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS - | KW_CONST | KW_CONSTEVAL | KW_CONSTEXPR | KW_CONSTINIT | KW_CONST_CAST - | KW_DECLTYPE | KW_DEFAULT | KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST - | KW_ELSE | KW_ENUM | KW_EXTERN | KW_EXPLICIT | KW_EXPLICIT_LPAREN - | KW_FALSE | KW_FINAL | KW_FLOAT | KW_FRIEND | KW_FOR - | KW_GOTO | KW_IF | KW_INLINE | KW_INT | KW_LONG | KW_MUTABLE - | KW_NAMESPACE | KW_NEW | KW_NOEXCEPT | KW_NOEXCEPT_LPAREN | KW_NULLPTR - | KW_OPERATOR | KW_OVERRIDE | KW_PRIVATE | KW_PROTECTED - | KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_REINTERPRET_CAST - | KW_RESTRICT | KW_RETURN | KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC - | KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT | KW_TEMPLATE - | KW_THREAD_LOCAL | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF - | KW_TYPEID | KW_TYPENAME | KW_UNDERLYING_TYPE | KW_UNION - | KW_UNSIGNED | KW_USING | KW_VIRTUAL | KW_VOID | KW_VOLATILE - | KW_WCHAR_T | KW_WHILE -{ -} - | '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%' - | '<' | '>' | '(' | ')' | '.' | ',' | ';' | ':' | '[' | ']' - | '?' | '{' code_block '}' - ; - -optional_const_expr: - empty -{ - $$ = nullptr; -} - | const_expr -{ - $$ = $1; -} - ; - -optional_const_expr_comma: - empty -{ - $$ = nullptr; -} - | const_expr_comma -{ - $$ = $1; -} - ; - -const_expr_comma: - const_expr -{ - $$ = $1; -} - | const_expr_comma ',' const_expr -{ - $$ = new CPPExpression(',', $1, $3); -} - ; - -no_angle_bracket_const_expr: - const_operand -{ - $$ = $1; -} - | '(' full_type ')' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::typecast_op($2, $4)); -} - | KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_static_cast)); -} - | KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_dynamic_cast)); -} - | KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_const_cast)); -} - | KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_reinterpret_cast)); -} - | KW_SIZEOF '(' full_type ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_func($3)); -} - | KW_SIZEOF no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_func($2)); -} - | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4)); -} - | KW_ALIGNOF '(' full_type ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::alignof_func($3)); -} - | '!' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_NOT, $2); -} - | '~' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_NEGATE, $2); -} - | '-' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_MINUS, $2); -} - | '+' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_PLUS, $2); -} - | '*' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_STAR, $2); -} - | '&' no_angle_bracket_const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_REF, $2); -} - | no_angle_bracket_const_expr '*' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('*', $1, $3); -} - | no_angle_bracket_const_expr '/' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('/', $1, $3); -} - | no_angle_bracket_const_expr '%' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('%', $1, $3); -} - | no_angle_bracket_const_expr '+' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('+', $1, $3); -} - | no_angle_bracket_const_expr '-' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('-', $1, $3); -} - | no_angle_bracket_const_expr '|' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('|', $1, $3); -} - | no_angle_bracket_const_expr '^' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('^', $1, $3); -} - | no_angle_bracket_const_expr '&' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('&', $1, $3); -} - | no_angle_bracket_const_expr OROR no_angle_bracket_const_expr -{ - $$ = new CPPExpression(OROR, $1, $3); -} - | no_angle_bracket_const_expr ANDAND no_angle_bracket_const_expr -{ - $$ = new CPPExpression(ANDAND, $1, $3); -} - | no_angle_bracket_const_expr EQCOMPARE no_angle_bracket_const_expr -{ - $$ = new CPPExpression(EQCOMPARE, $1, $3); -} - | no_angle_bracket_const_expr NECOMPARE no_angle_bracket_const_expr -{ - $$ = new CPPExpression(NECOMPARE, $1, $3); -} - | no_angle_bracket_const_expr LECOMPARE no_angle_bracket_const_expr -{ - $$ = new CPPExpression(LECOMPARE, $1, $3); -} - | no_angle_bracket_const_expr GECOMPARE no_angle_bracket_const_expr -{ - $$ = new CPPExpression(GECOMPARE, $1, $3); -} - | no_angle_bracket_const_expr SPACESHIP no_angle_bracket_const_expr -{ - $$ = new CPPExpression(SPACESHIP, $1, $3); -} - | no_angle_bracket_const_expr LSHIFT no_angle_bracket_const_expr -{ - $$ = new CPPExpression(LSHIFT, $1, $3); -} - | no_angle_bracket_const_expr RSHIFT no_angle_bracket_const_expr -{ - $$ = new CPPExpression(RSHIFT, $1, $3); -} - | no_angle_bracket_const_expr '?' no_angle_bracket_const_expr ':' no_angle_bracket_const_expr -{ - $$ = new CPPExpression('?', $1, $3, $5); -} - | no_angle_bracket_const_expr '[' const_expr ']' -{ - $$ = new CPPExpression('[', $1, $3); -} - | no_angle_bracket_const_expr '(' const_expr_comma ')' -{ - $$ = new CPPExpression('f', $1, $3); -} - | no_angle_bracket_const_expr '(' ')' -{ - $$ = new CPPExpression('f', $1); -} - | no_angle_bracket_const_expr '.' name -{ - $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer)); -} - | no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr -{ - $$ = new CPPExpression(POINTSAT, $1, $3); -} - | '(' const_expr_comma ')' -{ - $$ = $2; -} - ; - - -const_expr: - const_operand -{ - $$ = $1; -} - | '(' full_type ')' const_expr %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::typecast_op($2, $4)); -} - | KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_static_cast)); -} - | KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_dynamic_cast)); -} - | KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_const_cast)); -} - | KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_reinterpret_cast)); -} - | TYPENAME_IDENTIFIER '(' optional_const_expr_comma ')' -{ - // A constructor call. - CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert(type != nullptr); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}' -{ - // Aggregate initialization. - CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer); - if (type == nullptr) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert(type != nullptr); - $$ = new CPPExpression(CPPExpression::aggregate_init_op(type, $3)); -} - | KW_INT '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_CHAR '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_WCHAR_T '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_CHAR8_T '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char8_t)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_CHAR16_T '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_CHAR32_T '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_BOOL '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_SHORT '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_short)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_LONG '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_long)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_UNSIGNED '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_unsigned)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_SIGNED '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_signed)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_FLOAT '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_DOUBLE '(' optional_const_expr_comma ')' -{ - CPPType *type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); - $$ = new CPPExpression(CPPExpression::construct_op(type, $3)); -} - | KW_SIZEOF '(' full_type ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_func($3)); -} - | KW_SIZEOF const_expr %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_func($2)); -} - | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4)); -} - | KW_ALIGNOF '(' full_type ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::alignof_func($3)); -} - | KW_NEW predefined_type %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::new_op($2)); -} - | KW_NEW predefined_type '(' optional_const_expr_comma ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::new_op($2, $4)); -} - | KW_TYPEID '(' full_type ')' -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", @1); - } - $$ = new CPPExpression(CPPExpression::typeid_op($3, std_type_info)); -} - | KW_TYPEID '(' const_expr ')' -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", @1); - } - $$ = new CPPExpression(CPPExpression::typeid_op($3, std_type_info)); -} - | '!' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_NOT, $2); -} - | '~' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_NEGATE, $2); -} - | '-' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_MINUS, $2); -} - | '+' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_PLUS, $2); -} - | '*' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_STAR, $2); -} - | '&' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_REF, $2); -} - | const_expr '*' const_expr -{ - $$ = new CPPExpression('*', $1, $3); -} - | const_expr '/' const_expr -{ - $$ = new CPPExpression('/', $1, $3); -} - | const_expr '%' const_expr -{ - $$ = new CPPExpression('%', $1, $3); -} - | const_expr '+' const_expr -{ - $$ = new CPPExpression('+', $1, $3); -} - | const_expr '-' const_expr -{ - $$ = new CPPExpression('-', $1, $3); -} - | const_expr '|' const_expr -{ - $$ = new CPPExpression('|', $1, $3); -} - | const_expr '^' const_expr -{ - $$ = new CPPExpression('^', $1, $3); -} - | const_expr '&' const_expr -{ - $$ = new CPPExpression('&', $1, $3); -} - | const_expr OROR const_expr -{ - $$ = new CPPExpression(OROR, $1, $3); -} - | const_expr ANDAND const_expr -{ - $$ = new CPPExpression(ANDAND, $1, $3); -} - | const_expr EQCOMPARE const_expr -{ - $$ = new CPPExpression(EQCOMPARE, $1, $3); -} - | const_expr NECOMPARE const_expr -{ - $$ = new CPPExpression(NECOMPARE, $1, $3); -} - | const_expr LECOMPARE const_expr -{ - $$ = new CPPExpression(LECOMPARE, $1, $3); -} - | const_expr GECOMPARE const_expr -{ - $$ = new CPPExpression(GECOMPARE, $1, $3); -} - | const_expr SPACESHIP const_expr -{ - $$ = new CPPExpression(SPACESHIP, $1, $3); -} - | const_expr '<' const_expr -{ - $$ = new CPPExpression('<', $1, $3); -} - | const_expr '>' const_expr -{ - $$ = new CPPExpression('>', $1, $3); -} - | const_expr LSHIFT const_expr -{ - $$ = new CPPExpression(LSHIFT, $1, $3); -} - | const_expr RSHIFT const_expr -{ - $$ = new CPPExpression(RSHIFT, $1, $3); -} - | const_expr '?' const_expr ':' const_expr -{ - $$ = new CPPExpression('?', $1, $3, $5); -} - | const_expr '[' const_expr ']' -{ - $$ = new CPPExpression('[', $1, $3); -} - | const_expr '(' const_expr_comma ')' -{ - $$ = new CPPExpression('f', $1, $3); -} - | const_expr '(' ')' -{ - $$ = new CPPExpression('f', $1); -} - | KW_NOEXCEPT_LPAREN const_expr ')' -{ - $$ = new CPPExpression(KW_NOEXCEPT, $2); -} - | const_expr '.' name -{ - $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer)); -} - | const_expr POINTSAT const_expr -{ - $$ = new CPPExpression(POINTSAT, $1, $3); -} - | '(' const_expr_comma ')' -{ - $$ = $2; -} - ; - -const_operand: - INTEGER -{ - $$ = new CPPExpression($1); -} - | KW_TRUE -{ - $$ = new CPPExpression(true); -} - | KW_FALSE -{ - $$ = new CPPExpression(false); -} - | CHAR_TOK -{ - $$ = new CPPExpression($1); -} - | REAL -{ - $$ = new CPPExpression($1); -} - | string_literal -{ - $$ = $1; -} - | CUSTOM_LITERAL -{ - $$ = $1; -} - | IDENTIFIER -{ - $$ = new CPPExpression($1, current_scope, global_scope, current_lexer); -} - | KW_FINAL -{ - // A variable named "final". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("final", @1); - $$ = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} - | KW_OVERRIDE -{ - // A variable named "override". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("override", @1); - $$ = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} - | KW_NULLPTR -{ - $$ = new CPPExpression(CPPExpression::get_nullptr()); -} - | '[' capture_list ']' function_post optional_attributes maybe_trailing_return_type '{' code '}' -{ - $2->_flags = $4; - $2->_attributes = $5; - $2->_return_type = $6; - $$ = new CPPExpression(CPPExpression::lambda($2)); -} - | '[' capture_list ']' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type '{' code '}' -{ - $2->_parameters = $5; - $2->_flags = $7; - $2->_attributes = $8; - $2->_return_type = $9; - $$ = new CPPExpression(CPPExpression::lambda($2)); -} - | KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_HAS_VIRTUAL_DESTRUCTOR, $3)); -} - | KW_IS_ABSTRACT '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ABSTRACT, $3)); -} - | KW_IS_BASE_OF '(' full_type ',' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3, $5)); -} - | KW_IS_CLASS '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3)); -} - | KW_IS_CONSTRUCTIBLE '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3)); -} - | KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3, $5)); -} - | KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONVERTIBLE_TO, $3, $5)); -} - | KW_IS_DESTRUCTIBLE '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_DESTRUCTIBLE, $3)); -} - | KW_IS_EMPTY '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_EMPTY, $3)); -} - | KW_IS_ENUM '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ENUM, $3)); -} - | KW_IS_FINAL '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FINAL, $3)); -} - | KW_IS_FUNDAMENTAL '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FUNDAMENTAL, $3)); -} - | KW_IS_POD '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POD, $3)); -} - | KW_IS_POLYMORPHIC '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POLYMORPHIC, $3)); -} - | KW_IS_STANDARD_LAYOUT '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_STANDARD_LAYOUT, $3)); -} - | KW_IS_TRIVIAL '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, $3)); -} - | KW_IS_TRIVIALLY_COPYABLE '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIALLY_COPYABLE, $3)); -} - | KW_IS_UNION '(' full_type ')' -{ - $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_UNION, $3)); -} - ; - -/* This is used for a const_expr as a "formal parameter", which really - means an instance declaration using a parameter list (which looks a - lot like a function prototype). It differs from const_expr mainly - in that it forbids some expressions unless they are parenthesized, - to avoid shift/reduce conflicts with the actual formal parameter - definition. */ - -formal_const_expr: - formal_const_operand -{ - $$ = $1; -} - | '(' full_type ')' const_expr %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::typecast_op($2, $4)); -} - | KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_static_cast)); -} - | KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_dynamic_cast)); -} - | KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_const_cast)); -} - | KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' -{ - $$ = new CPPExpression(CPPExpression::typecast_op($3, $6, CPPExpression::T_reinterpret_cast)); -} - | KW_SIZEOF '(' full_type ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_func($3)); -} - | KW_SIZEOF formal_const_expr %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_func($2)); -} - | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4)); -} - | KW_ALIGNOF '(' full_type ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::alignof_func($3)); -} - | KW_NEW predefined_type %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::new_op($2)); -} - | KW_NEW predefined_type '(' optional_const_expr_comma ')' %prec UNARY -{ - $$ = new CPPExpression(CPPExpression::new_op($2, $4)); -} - | KW_TYPEID '(' full_type ')' -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", @1); - } - $$ = new CPPExpression(CPPExpression::typeid_op($3, std_type_info)); -} - | KW_TYPEID '(' const_expr ')' -{ - CPPIdentifier ident(""); - ident.add_name("std"); - ident.add_name("type_info"); - CPPType *std_type_info = ident.find_type(current_scope, global_scope, false, current_lexer); - if (!std_type_info) { - yywarning("cannot use typeid before including ", @1); - } - $$ = new CPPExpression(CPPExpression::typeid_op($3, std_type_info)); -} - | '!' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_NOT, $2); -} - | '~' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_NEGATE, $2); -} - | '-' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_MINUS, $2); -} - | '+' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_PLUS, $2); -} - | '&' const_expr %prec UNARY -{ - $$ = new CPPExpression(UNARY_REF, $2); -} - | formal_const_expr '*' const_expr -{ - $$ = new CPPExpression('*', $1, $3); -} - | formal_const_expr '/' const_expr -{ - $$ = new CPPExpression('/', $1, $3); -} - | formal_const_expr '%' const_expr -{ - $$ = new CPPExpression('%', $1, $3); -} - | formal_const_expr '+' const_expr -{ - $$ = new CPPExpression('+', $1, $3); -} - | formal_const_expr '-' const_expr -{ - $$ = new CPPExpression('-', $1, $3); -} - | formal_const_expr '|' const_expr -{ - $$ = new CPPExpression('|', $1, $3); -} - | formal_const_expr '^' const_expr -{ - $$ = new CPPExpression('^', $1, $3); -} - | formal_const_expr '&' const_expr -{ - $$ = new CPPExpression('&', $1, $3); -} - | formal_const_expr OROR const_expr -{ - $$ = new CPPExpression(OROR, $1, $3); -} - | formal_const_expr ANDAND const_expr -{ - $$ = new CPPExpression(ANDAND, $1, $3); -} - | formal_const_expr EQCOMPARE const_expr -{ - $$ = new CPPExpression(EQCOMPARE, $1, $3); -} - | formal_const_expr NECOMPARE const_expr -{ - $$ = new CPPExpression(NECOMPARE, $1, $3); -} - | formal_const_expr LECOMPARE const_expr -{ - $$ = new CPPExpression(LECOMPARE, $1, $3); -} - | formal_const_expr GECOMPARE const_expr -{ - $$ = new CPPExpression(GECOMPARE, $1, $3); -} - | formal_const_expr SPACESHIP const_expr -{ - $$ = new CPPExpression(SPACESHIP, $1, $3); -} - | formal_const_expr '<' const_expr -{ - $$ = new CPPExpression('<', $1, $3); -} - | formal_const_expr '>' const_expr -{ - $$ = new CPPExpression('>', $1, $3); -} - | formal_const_expr LSHIFT const_expr -{ - $$ = new CPPExpression(LSHIFT, $1, $3); -} - | formal_const_expr RSHIFT const_expr -{ - $$ = new CPPExpression(RSHIFT, $1, $3); -} - | formal_const_expr '?' const_expr ':' const_expr -{ - $$ = new CPPExpression('?', $1, $3, $5); -} - | formal_const_expr '[' const_expr ']' -{ - $$ = new CPPExpression('[', $1, $3); -} - | formal_const_expr '(' const_expr_comma ')' -{ - $$ = new CPPExpression('f', $1, $3); -} - | formal_const_expr '(' ')' -{ - $$ = new CPPExpression('f', $1); -} - | formal_const_expr '.' name -{ - $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer)); -} - | formal_const_expr POINTSAT const_expr -{ - $$ = new CPPExpression(POINTSAT, $1, $3); -} - | '(' const_expr_comma ')' -{ - $$ = $2; -} - ; - -formal_const_operand: - INTEGER -{ - $$ = new CPPExpression($1); -} - | KW_TRUE -{ - $$ = new CPPExpression(true); -} - | KW_FALSE -{ - $$ = new CPPExpression(false); -} - | CHAR_TOK -{ - $$ = new CPPExpression($1); -} - | REAL -{ - $$ = new CPPExpression($1); -} - | string_literal -{ - $$ = $1; -} - | CUSTOM_LITERAL -{ - $$ = $1; -} - | IDENTIFIER -{ - $$ = new CPPExpression($1, current_scope, global_scope, current_lexer); -} - | KW_FINAL -{ - // A variable named "final". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("final", @1); - $$ = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} - | KW_OVERRIDE -{ - // A variable named "override". C++11 explicitly permits this. - CPPIdentifier *ident = new CPPIdentifier("override", @1); - $$ = new CPPExpression(ident, current_scope, global_scope, current_lexer); -} - | KW_NULLPTR -{ - $$ = new CPPExpression(CPPExpression::get_nullptr()); -} - ; - -/* The contents of the [] list preceding a lambda expression. */ -capture_list: - empty -{ - $$ = new CPPClosureType(); -} - | '=' -{ - $$ = new CPPClosureType(CPPClosureType::CT_by_value); -} - | '&' -{ - $$ = new CPPClosureType(CPPClosureType::CT_by_reference); -} - | capture maybe_initialize -{ - $$ = new CPPClosureType(); - $1->_initializer = $2; - $$->_captures.push_back(*$1); - delete $1; -} - | capture_list ',' capture maybe_initialize -{ - $$ = $1; - $3->_initializer = $4; - $$->_captures.push_back(*$3); - delete $3; -} - ; - -capture: - '&' name -{ - $$ = new CPPClosureType::Capture; - $$->_name = $2->get_simple_name(); - $$->_type = CPPClosureType::CT_by_reference; -} - | '&' name ELLIPSIS -{ - $$ = new CPPClosureType::Capture; - $$->_name = $2->get_simple_name(); - $$->_type = CPPClosureType::CT_by_reference; -} - | name -{ - $$ = new CPPClosureType::Capture; - $$->_name = $1->get_simple_name(); - if ($$->_name == "this") { - $$->_type = CPPClosureType::CT_by_reference; - } else { - $$->_type = CPPClosureType::CT_by_value; - } -} - | '*' name -{ - $$ = new CPPClosureType::Capture; - $$->_name = $2->get_simple_name(); - $$->_type = CPPClosureType::CT_by_value; - if ($$->_name != "this") { - yywarning("only capture name 'this' may be preceded by an asterisk", @2); - } -} - ; - -class_derivation_name: - name -{ - CPPType *type = $1->find_type(current_scope, global_scope, true); - if (type == nullptr) { - type = CPPType::new_type(new CPPTBDType($1)); - } - $$ = type; -} - | KW_TYPENAME name -{ - $$ = CPPType::new_type(new CPPTBDType($2)); -} - | name ELLIPSIS -{ - CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($1); - ctp->_packed = true; - $$ = CPPType::new_type(ctp); -} - ; - -/* -typedefname: - TYPENAME_IDENTIFIER -{ - CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer); - if (type == NULL) { - yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1); - } - assert(type != NULL); - $$ = type; -} - | KW_TYPENAME name -{ - $$ = CPPType::new_type(new CPPTBDType($2)); -} - ; -*/ - - -/* Note that we should also accept "final" and "override" as valid names, - * according to C++11. */ -name: - IDENTIFIER -{ - $$ = $1; -} - | TYPENAME_IDENTIFIER -{ - $$ = $1; -} - | TYPEPACK_IDENTIFIER -{ - $$ = $1; -} - | KW_FINAL -{ - $$ = new CPPIdentifier("final", @1); -} - | KW_OVERRIDE -{ - $$ = new CPPIdentifier("override", @1); -} - | KW_SIGNED -{ - // This is not a keyword in Python, so it is useful to be able to use this - // in MAKE_PROPERTY definitions, etc. - $$ = new CPPIdentifier("signed", @1); -} - | KW_FLOAT -{ - $$ = new CPPIdentifier("float", @1); -} - | KW_PUBLIC -{ - $$ = new CPPIdentifier("public", @1); -} - | KW_PRIVATE -{ - $$ = new CPPIdentifier("private", @1); -} - | KW_STATIC -{ - $$ = new CPPIdentifier("static", @1); -} - | KW_DEFAULT -{ - $$ = new CPPIdentifier("default", @1); -} - ; - - -/* A variant on name that's used for structs, where we disallow final - * to disambiguate the case of struct A final {}; - */ -name_no_final: - IDENTIFIER -{ - $$ = $1; -} - | TYPENAME_IDENTIFIER -{ - $$ = $1; -} - | TYPEPACK_IDENTIFIER -{ - $$ = $1; -} - | KW_OVERRIDE -{ - $$ = new CPPIdentifier("override", @1); -} - ; - - -string_literal: - SIMPLE_STRING -{ - $$ = new CPPExpression($1); -} - | STRING_LITERAL -{ - $$ = $1; -} - | string_literal SIMPLE_STRING -{ - // The right string takes on the literal type of the left. - $$ = $1; - $$->_str += $2; -} - | string_literal STRING_LITERAL -{ - // We have to check that the two literal types match up. - $$ = $1; - if ($2->_type != CPPExpression::T_string && $2->_type != $1->_type) { - yywarning("cannot concatenate two string literals of different types", @$); - } - $$->_str += $2->_str; -} - ; - -empty: - ; diff --git a/dtool/src/cppparser/cppBisonDefs.h b/dtool/src/cppparser/cppBisonDefs.h deleted file mode 100644 index 2859ee30ab..0000000000 --- a/dtool/src/cppparser/cppBisonDefs.h +++ /dev/null @@ -1,124 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppBisonDefs.h - * @author drose - * @date 1999-01-17 - */ - -#ifndef CPPBISON_H -#define CPPBISON_H - -// This header file defines the interface to the yacc (actually, bison) parser -// and grammar. None of these interfaces are intended to be used directly; -// they're defined here strictly to be used by the CPPParser and -// CPPExpressionParser classes. - -#include "dtoolbase.h" - -#include - -#include "cppAttributeList.h" -#include "cppClosureType.h" -#include "cppExtensionType.h" -#include "cppFile.h" - -class CPPParser; -class CPPExpression; -class CPPPreprocessor; -class CPPDeclaration; -class CPPInstance; -class CPPType; -class CPPStructType; -class CPPEnumType; -class CPPSimpleType; -class CPPInstanceIdentifier; -class CPPParameterList; -class CPPTemplateParameterList; -class CPPScope; -class CPPIdentifier; -class CPPCaptureType; - -void parse_cpp(CPPParser *cp); -CPPExpression *parse_const_expr(CPPPreprocessor *pp, - CPPScope *new_current_scope, - CPPScope *new_global_scope); -CPPType *parse_type(CPPPreprocessor *pp, - CPPScope *new_current_scope, - CPPScope *new_global_scope); - -extern CPPScope *current_scope; -extern CPPScope *global_scope; -extern CPPPreprocessor *current_lexer; - - -// This structure holds the return value for each token. Traditionally, this -// is a union, and is declared with the %union declaration in the parser.y -// file, but unions are pretty worthless in C++ (you can't include an object -// that has member functions in a union), so we'll use a class instead. That -// means we need to declare it externally, here. - -class cppyystype { -public: - std::string str; - CPPAttributeList attr_list; - union { - unsigned long long integer; - long double real; - CPPScope *scope; - CPPDeclaration *decl; - CPPInstance *instance; - CPPType *type; - CPPStructType *struct_type; - CPPEnumType *enum_type; - CPPSimpleType *simple_type; - CPPInstanceIdentifier *inst_ident; - CPPParameterList *param_list; - CPPTemplateParameterList *template_param_list; - CPPExtensionType::Type extension_enum; - CPPExpression *expr; - CPPIdentifier *identifier; - CPPClosureType *closure_type; - CPPClosureType::Capture *capture; - } u; -}; -#define YYSTYPE cppyystype - -// This structure takes advantage of a bison feature to track the exact -// location in the file of each token, for more useful error reporting. We -// define it up here so we can reference it in the lexer. - -struct cppyyltype { - // Bison expects these members to be part of this struct. - int first_line; - int first_column; - int last_line; - int last_column; - - // Early versions of bison (1.25 and earlier) expected these members to be - // in this struct as well. - int timestamp; - char *text; - - // The remaining members are added for this application and have no meaning - // to bison. - CPPFile file; -}; -#define YYLTYPE cppyyltype - -// Beginning around bison 1.35 or so, we need to define this macro as well, to -// tell bison how to collect multiple locations together. (The default -// implementation copies only first_line through last_column, whereas here we -// use the struct assignment operator to copy all the members of the -// structure). -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - (Current) = (Rhs)[1]; \ - (Current).last_line = (Rhs)[N].last_line; \ - (Current).last_column = (Rhs)[N].last_column; - -#endif diff --git a/dtool/src/cppparser/cppClassTemplateParameter.cxx b/dtool/src/cppparser/cppClassTemplateParameter.cxx deleted file mode 100644 index 7c85eb6c24..0000000000 --- a/dtool/src/cppparser/cppClassTemplateParameter.cxx +++ /dev/null @@ -1,126 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppClassTemplateParameter.cxx - * @author drose - * @date 1999-10-28 - */ - -#include "cppClassTemplateParameter.h" -#include "cppIdentifier.h" - -/** - * - */ -CPPClassTemplateParameter:: -CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) : - CPPType(CPPFile()), - _ident(ident), - _default_type(default_type), - _packed(false) -{ -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPClassTemplateParameter:: -is_fully_specified() const { - return false; -} - -/** - * - */ -void CPPClassTemplateParameter:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (complete) { - out << "class"; - if (_packed) { - out << "..."; - } - if (_ident != nullptr) { - out << " "; - _ident->output(out, scope); - } - if (_default_type) { - out << " = "; - _default_type->output(out, indent_level, scope, false); - } - } else { - _ident->output(out, scope); - } -} - - -/** - * - */ -CPPDeclaration::SubType CPPClassTemplateParameter:: -get_subtype() const { - return ST_class_template_parameter; -} - -/** - * - */ -CPPClassTemplateParameter *CPPClassTemplateParameter:: -as_class_template_parameter() { - return this; -} - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPClassTemplateParameter:: -is_equal(const CPPDeclaration *other) const { - const CPPClassTemplateParameter *ot = ((CPPDeclaration *)other)->as_class_template_parameter(); - assert(ot != nullptr); - - if (_default_type != ot->_default_type) { - return false; - } - - if (_packed != ot->_packed) { - return false; - } - - if (_ident == nullptr || ot->_ident == nullptr) { - return _ident == ot->_ident; - } - - return *_ident == *ot->_ident; -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPClassTemplateParameter:: -is_less(const CPPDeclaration *other) const { - const CPPClassTemplateParameter *ot = ((CPPDeclaration *)other)->as_class_template_parameter(); - assert(ot != nullptr); - - if (_default_type != ot->_default_type) { - return _default_type < ot->_default_type; - } - - if (_packed != ot->_packed) { - return _packed < ot->_packed; - } - - if (_ident == nullptr || ot->_ident == nullptr) { - return _ident < ot->_ident; - } - - return *_ident < *ot->_ident; -} diff --git a/dtool/src/cppparser/cppClassTemplateParameter.h b/dtool/src/cppparser/cppClassTemplateParameter.h deleted file mode 100644 index 8ff6fe1538..0000000000 --- a/dtool/src/cppparser/cppClassTemplateParameter.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppClassTemplateParameter.h - * @author drose - * @date 1999-10-28 - */ - -#ifndef CPPCLASSTEMPLATEPARAMETER_H -#define CPPCLASSTEMPLATEPARAMETER_H - -#include "dtoolbase.h" - -#include "cppType.h" - -class CPPIdentifier; - -/** - * - */ -class CPPClassTemplateParameter : public CPPType { -public: - CPPClassTemplateParameter(CPPIdentifier *ident, - CPPType *default_type = nullptr); - - virtual bool is_fully_specified() const; - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPClassTemplateParameter *as_class_template_parameter(); - - CPPIdentifier *_ident; - CPPType *_default_type; - bool _packed; - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppClosureType.cxx b/dtool/src/cppparser/cppClosureType.cxx deleted file mode 100644 index 5c201580f1..0000000000 --- a/dtool/src/cppparser/cppClosureType.cxx +++ /dev/null @@ -1,200 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppClosureType.cxx - * @author rdb - * @date 2017-01-14 - */ - -#include "cppClosureType.h" -#include "cppParameterList.h" -#include "cppExpression.h" - -/** - * - */ -CPPClosureType:: -CPPClosureType(CaptureType default_capture) : - CPPFunctionType(nullptr, nullptr, 0), - _default_capture(default_capture) { -} - -/** - * - */ -CPPClosureType:: -CPPClosureType(const CPPClosureType ©) : - CPPFunctionType(copy), - _captures(copy._captures), - _default_capture(copy._default_capture) -{ -} - -/** - * - */ -void CPPClosureType:: -operator = (const CPPClosureType ©) { - CPPFunctionType::operator = (copy); - _captures = copy._captures; - _default_capture = copy._default_capture; -} - -/** - * Adds a new capture to the beginning of the capture list. - */ -void CPPClosureType:: -add_capture(std::string name, CaptureType type, CPPExpression *initializer) { - if (type == CT_none) { - if (name == "this") { - type = CT_by_reference; - } else { - type = CT_by_value; - } - } - - Capture capture = {std::move(name), type, initializer}; - _captures.insert(_captures.begin(), std::move(capture)); -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPClosureType:: -is_fully_specified() const { - return CPPFunctionType::is_fully_specified(); -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPClosureType:: -is_default_constructible() const { - return false; -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPClosureType:: -is_copy_constructible() const { - return true; -} - -/** - * Returns true if the type is destructible. - */ -bool CPPClosureType:: -is_destructible() const { - return true; -} - -/** - * - */ -void CPPClosureType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - out.put('['); - - bool have_capture = false; - switch (_default_capture) { - case CT_none: - break; - case CT_by_reference: - out.put('&'); - have_capture = true; - break; - case CT_by_value: - out.put('='); - have_capture = true; - break; - } - - Captures::const_iterator it; - for (it = _captures.begin(); it != _captures.end(); ++it) { - const Capture &capture = *it; - if (have_capture) { - out << ", "; - } - if (capture._name == "this") { - if (capture._type == CT_by_value) { - out.put('*'); - } - } else { - if (capture._type == CT_by_reference) { - out.put('&'); - } - } - out << capture._name; - - if (capture._initializer != nullptr) { - out << " = " << *capture._initializer; - } - - have_capture = true; - } - out.put(']'); - - if (_parameters != nullptr) { - out.put('('); - _parameters->output(out, scope, true, -1); - out.put(')'); - } - - if (_flags & F_noexcept) { - out << " noexcept"; - } - - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - - if (_return_type != nullptr) { - out << " -> "; - _return_type->output(out, indent_level, scope, false); - } - - out << " {}"; -} - -/** - * - */ -CPPDeclaration::SubType CPPClosureType:: -get_subtype() const { - return ST_closure; -} - -/** - * - */ -CPPClosureType *CPPClosureType:: -as_closure_type() { - return this; -} - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPClosureType:: -is_equal(const CPPDeclaration *other) const { - return (this == other); -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPClosureType:: -is_less(const CPPDeclaration *other) const { - return (this < other); -} diff --git a/dtool/src/cppparser/cppClosureType.h b/dtool/src/cppparser/cppClosureType.h deleted file mode 100644 index 9e11a2f124..0000000000 --- a/dtool/src/cppparser/cppClosureType.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppClosureType.h - * @author rdb - * @date 2017-01-14 - */ - -#ifndef CPPCLOSURETYPE_H -#define CPPCLOSURETYPE_H - -#include "dtoolbase.h" - -#include "cppFunctionType.h" - -/** - * The type of a lambda expression. This is like a function, but with - * additional captures defined. - */ -class CPPClosureType : public CPPFunctionType { -public: - enum CaptureType { - CT_none, - CT_by_reference, - CT_by_value, - }; - - CPPClosureType(CaptureType default_capture = CT_none); - CPPClosureType(const CPPClosureType ©); - void operator = (const CPPClosureType ©); - - struct Capture { - std::string _name; - CaptureType _type; - CPPExpression *_initializer; - }; - typedef std::vector Captures; - Captures _captures; - - CaptureType _default_capture; - - void add_capture(std::string name, CaptureType type, CPPExpression *initializer = nullptr); - - virtual bool is_fully_specified() const; - - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_destructible() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - virtual CPPClosureType *as_closure_type(); - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppCommentBlock.cxx b/dtool/src/cppparser/cppCommentBlock.cxx deleted file mode 100644 index 46865ba44d..0000000000 --- a/dtool/src/cppparser/cppCommentBlock.cxx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppCommentBlock.cxx - * @author drose - * @date 2000-08-15 - */ - -#include "cppCommentBlock.h" diff --git a/dtool/src/cppparser/cppCommentBlock.h b/dtool/src/cppparser/cppCommentBlock.h deleted file mode 100644 index e31b3b6278..0000000000 --- a/dtool/src/cppparser/cppCommentBlock.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppCommentBlock.h - * @author drose - * @date 2000-08-15 - */ - -#ifndef CPPCOMMENTBLOCK_H -#define CPPCOMMENTBLOCK_H - -#include "dtoolbase.h" - -#include "cppFile.h" - -#include - -/** - * This represents a comment appearing in the source code. The - * CPPPreprocessor collects these, and saves the complete list of comments - * encountered; it also stores a list of the comment blocks appearing before - * each declaration. - */ -class CPPCommentBlock { -public: - CPPFile _file; - int _line_number; - int _col_number; - int _last_line; - bool _c_style; - std::string _comment; -}; - -typedef std::list CPPComments; - -#endif diff --git a/dtool/src/cppparser/cppConstType.cxx b/dtool/src/cppparser/cppConstType.cxx deleted file mode 100644 index 585f545b63..0000000000 --- a/dtool/src/cppparser/cppConstType.cxx +++ /dev/null @@ -1,240 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppConstType.cxx - * @author drose - * @date 1999-10-28 - */ - -#include "cppConstType.h" - -/** - * - */ -CPPConstType:: -CPPConstType(CPPType *wrapped_around) : - CPPType(CPPFile()), - _wrapped_around(wrapped_around) -{ -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPConstType:: -is_fully_specified() const { - return CPPType::is_fully_specified() && - _wrapped_around->is_fully_specified(); -} - -/** - * - */ -CPPDeclaration *CPPConstType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPConstType *rep = new CPPConstType(*this); - rep->_wrapped_around = - _wrapped_around->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - - if (rep->_wrapped_around == _wrapped_around) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_const_type(); - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPConstType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *ptype = _wrapped_around->resolve_type(current_scope, global_scope); - - if (ptype != _wrapped_around) { - CPPConstType *rep = new CPPConstType(*this); - rep->_wrapped_around = ptype; - return CPPType::new_type(rep); - } - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPConstType:: -is_tbd() const { - return _wrapped_around->is_tbd(); -} - -/** - * Returns true if the type is considered a fundamental type. - */ -bool CPPConstType:: -is_fundamental() const { - return _wrapped_around->is_fundamental(); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPConstType:: -is_standard_layout() const { - return _wrapped_around->is_standard_layout(); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPConstType:: -is_trivial() const { - return _wrapped_around->is_trivial(); -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPConstType:: -is_trivially_copyable() const { - return _wrapped_around->is_trivially_copyable(); -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPConstType:: -is_constructible(const CPPType *given_type) const { - return _wrapped_around->is_constructible(given_type); -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPConstType:: -is_default_constructible() const { - return _wrapped_around->is_default_constructible(); -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPConstType:: -is_copy_constructible() const { - return _wrapped_around->is_copy_constructible(); -} - -/** - * Returns true if the type is destructible. - */ -bool CPPConstType:: -is_destructible() const { - return _wrapped_around->is_destructible(); -} - -/** - * Returns true if variables of this type may be implicitly converted to - * the other type. - */ -bool CPPConstType:: -is_convertible_to(const CPPType *other) const { - return _wrapped_around->is_convertible_to(other); -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPConstType:: -is_equivalent(const CPPType &other) const { - const CPPConstType *ot = ((CPPType *)&other)->as_const_type(); - if (ot == nullptr) { - return CPPType::is_equivalent(other); - } - - return _wrapped_around->is_equivalent(*ot->_wrapped_around); -} - -/** - * - */ -void CPPConstType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - _wrapped_around->output(out, indent_level, scope, complete); - out << " const"; -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPConstType:: -output_instance(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const { - _wrapped_around->output_instance(out, indent_level, scope, complete, - "const " + prename, name); -} - -/** - * - */ -CPPDeclaration::SubType CPPConstType:: -get_subtype() const { - return ST_const; -} - -/** - * - */ -CPPConstType *CPPConstType:: -as_const_type() { - return this; -} - - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPConstType:: -is_equal(const CPPDeclaration *other) const { - const CPPConstType *ot = ((CPPDeclaration *)other)->as_const_type(); - assert(ot != nullptr); - - return _wrapped_around == ot->_wrapped_around; -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPConstType:: -is_less(const CPPDeclaration *other) const { - const CPPConstType *ot = ((CPPDeclaration *)other)->as_const_type(); - assert(ot != nullptr); - - return _wrapped_around < ot->_wrapped_around; -} diff --git a/dtool/src/cppparser/cppConstType.h b/dtool/src/cppparser/cppConstType.h deleted file mode 100644 index 81db17884a..0000000000 --- a/dtool/src/cppparser/cppConstType.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppConstType.h - * @author drose - * @date 1999-10-28 - */ - -#ifndef CPPCONSTTYPE_H -#define CPPCONSTTYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -/** - * - */ -class CPPConstType : public CPPType { -public: - CPPConstType(CPPType *wrapped_around); - - CPPType *_wrapped_around; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - virtual bool is_fundamental() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_destructible() const; - virtual bool is_convertible_to(const CPPType *other) const; - virtual bool is_equivalent(const CPPType &other) const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - - virtual SubType get_subtype() const; - - virtual CPPConstType *as_const_type(); - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppDeclaration.cxx b/dtool/src/cppparser/cppDeclaration.cxx deleted file mode 100644 index ef7e87bdf6..0000000000 --- a/dtool/src/cppparser/cppDeclaration.cxx +++ /dev/null @@ -1,379 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppDeclaration.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppDeclaration.h" -#include "cppPreprocessor.h" - -/** - * - */ -CPPDeclaration:: -CPPDeclaration(const CPPFile &file, CPPAttributeList attr) : - _file(file), - _attributes(std::move(attr)) -{ - _vis = V_unknown; - _template_scope = nullptr; - _leading_comment = nullptr; -} - -/** - * - */ -CPPDeclaration:: -CPPDeclaration(const CPPDeclaration ©) : - _vis(copy._vis), - _template_scope(copy._template_scope), - _file(copy._file), - _leading_comment(copy._leading_comment), - _attributes(copy._attributes) -{ -} - -/** - * - */ -CPPDeclaration &CPPDeclaration:: -operator = (const CPPDeclaration ©) { - _vis = copy._vis; - _template_scope = copy._template_scope; - _file = copy._file; - _leading_comment = copy._leading_comment; - _attributes = copy._attributes; - return *this; -} - -/** - * - */ -bool CPPDeclaration:: -operator == (const CPPDeclaration &other) const { - if (get_subtype() != other.get_subtype()) { - return false; - } - return is_equal(&other); -} - -/** - * - */ -bool CPPDeclaration:: -operator != (const CPPDeclaration &other) const { - return !(*this == other); -} - -/** - * - */ -bool CPPDeclaration:: -operator < (const CPPDeclaration &other) const { - if (get_subtype() != other.get_subtype()) { - return get_subtype() < other.get_subtype(); - } - return is_less(&other); -} - -/** - * Returns true if this is a template declaration of some kind: a template - * function or a template class, typically. - */ -bool CPPDeclaration:: -is_template() const { - return _template_scope != nullptr; -} - -/** - * If is_template(), above, returns true, this returns the CPPTemplateScope in - * which this particular template declaration is defined. This scope includes - * the information about the template parameters. - */ -CPPTemplateScope *CPPDeclaration:: -get_template_scope() const { - return _template_scope; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPDeclaration:: -is_fully_specified() const { - return !is_template(); -} - -/** - * - */ -CPPDeclaration *CPPDeclaration:: -instantiate(const CPPTemplateParameterList *, - CPPScope *, CPPScope *, - CPPPreprocessor *error_sink) const { - if (error_sink != nullptr) { - error_sink->warning("Ignoring template parameters"); - } - return (CPPDeclaration *)this; -} - -/** - * - */ -CPPDeclaration *CPPDeclaration:: -substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - assert((*si).second != nullptr); - return (*si).second; - } - return this; -} - -/** - * - */ -void CPPDeclaration:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - out << _attributes; -} - -/** - * - */ -CPPDeclaration::SubType CPPDeclaration:: -get_subtype() const { - return ST_empty; -} - -/** - * - */ -CPPInstance *CPPDeclaration:: -as_instance() { - return nullptr; -} - -/** - * - */ -CPPClassTemplateParameter *CPPDeclaration:: -as_class_template_parameter() { - return nullptr; -} - -/** - * - */ -CPPTypedefType *CPPDeclaration:: -as_typedef_type() { - return nullptr; -} - -/** - * - */ -CPPTypeDeclaration *CPPDeclaration:: -as_type_declaration() { - return nullptr; -} - -/** - * - */ -CPPExpression *CPPDeclaration:: -as_expression() { - return nullptr; -} - -/** - * - */ -CPPType *CPPDeclaration:: -as_type() { - return nullptr; -} - -/** - * - */ -CPPNamespace *CPPDeclaration:: -as_namespace() { - return nullptr; -} - -/** - * - */ -CPPUsing *CPPDeclaration:: -as_using() { - return nullptr; -} - -/** - * - */ -CPPSimpleType *CPPDeclaration:: -as_simple_type() { - return nullptr; -} - -/** - * - */ -CPPPointerType *CPPDeclaration:: -as_pointer_type() { - return nullptr; -} - -/** - * - */ -CPPReferenceType *CPPDeclaration:: -as_reference_type() { - return nullptr; -} - -/** - * - */ -CPPArrayType *CPPDeclaration:: -as_array_type() { - return nullptr; -} - -/** - * - */ -CPPConstType *CPPDeclaration:: -as_const_type() { - return nullptr; -} - -/** - * - */ -CPPFunctionType *CPPDeclaration:: -as_function_type() { - return nullptr; -} - -/** - * - */ -CPPFunctionGroup *CPPDeclaration:: -as_function_group() { - return nullptr; -} - -/** - * - */ -CPPExtensionType *CPPDeclaration:: -as_extension_type() { - return nullptr; -} - -/** - * - */ -CPPStructType *CPPDeclaration:: -as_struct_type() { - return nullptr; -} - -/** - * - */ -CPPEnumType *CPPDeclaration:: -as_enum_type() { - return nullptr; -} - -/** - * - */ -CPPTBDType *CPPDeclaration:: -as_tbd_type() { - return nullptr; -} - -/** - * - */ -CPPTypeProxy *CPPDeclaration:: -as_type_proxy() { - return nullptr; -} - -/** - * - */ -CPPMakeProperty *CPPDeclaration:: -as_make_property() { - return nullptr; -} - -/** - * - */ -CPPMakeSeq *CPPDeclaration:: -as_make_seq() { - return nullptr; -} - -/** - * - */ -CPPClosureType *CPPDeclaration:: -as_closure_type() { - return nullptr; -} - -/** - * Called by CPPDeclaration to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPDeclaration:: -is_equal(const CPPDeclaration *other) const { - return this == other; -} - -/** - * Called by CPPDeclaration to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPDeclaration:: -is_less(const CPPDeclaration *other) const { - return this < other; -} - - -std::ostream & -operator << (std::ostream &out, const CPPDeclaration::SubstDecl &subst) { - CPPDeclaration::SubstDecl::const_iterator it; - for (it = subst.begin(); it != subst.end(); ++it) { - out << " "; - if (it->first == nullptr) { - out << "(null)"; - } else { - out << *(it->first); - } - out << " -> "; - if (it->second == nullptr) { - out << "(null)"; - } else { - out << *(it->second); - } - out << "\n"; - } - return out; -} diff --git a/dtool/src/cppparser/cppDeclaration.h b/dtool/src/cppparser/cppDeclaration.h deleted file mode 100644 index 73c8fd49bb..0000000000 --- a/dtool/src/cppparser/cppDeclaration.h +++ /dev/null @@ -1,239 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppDeclaration.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPDECLARATION_H -#define CPPDECLARATION_H - -#include "dtoolbase.h" - -#include "cppVisibility.h" -#include "cppFile.h" -#include "cppCommentBlock.h" -#include "cppAttributeList.h" - -#include -#include -#include -#include - -class CPPInstance; -class CPPTemplateParameterList; -class CPPTypedefType; -class CPPTypeDeclaration; -class CPPExpression; -class CPPType; -class CPPNamespace; -class CPPUsing; -class CPPSimpleType; -class CPPPointerType; -class CPPReferenceType; -class CPPArrayType; -class CPPConstType; -class CPPFunctionType; -class CPPFunctionGroup; -class CPPExtensionType; -class CPPStructType; -class CPPEnumType; -class CPPTypeProxy; -class CPPMakeProperty; -class CPPMakeSeq; -class CPPClosureType; -class CPPClassTemplateParameter; -class CPPTBDType; -class CPPScope; -class CPPTemplateScope; -class CPPPreprocessor; - -/** - * - */ -class CPPDeclaration { -public: - enum SubType { - // Empty declaration - ST_empty, - - // Subtypes of CPPDeclaration - ST_instance, - ST_type_declaration, - ST_expression, - ST_type, - ST_namespace, - ST_using, - ST_make_property, - ST_make_seq, - - // Subtypes of CPPType - ST_simple, - ST_pointer, - ST_reference, - ST_array, - ST_const, - ST_function, - ST_function_group, - ST_extension, - ST_struct, - ST_enum, - ST_class_template_parameter, - ST_tbd, - ST_type_proxy, - ST_typedef, - ST_closure, - }; - - CPPDeclaration(const CPPFile &file, CPPAttributeList attr = CPPAttributeList()); - CPPDeclaration(const CPPDeclaration ©); - virtual ~CPPDeclaration() {}; - - CPPDeclaration &operator = (const CPPDeclaration ©); - - bool operator == (const CPPDeclaration &other) const; - bool operator != (const CPPDeclaration &other) const; - bool operator < (const CPPDeclaration &other) const; - - bool is_template() const; - CPPTemplateScope *get_template_scope() const; - virtual bool is_fully_specified() const; - virtual CPPDeclaration * - instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - typedef std::map SubstDecl; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - typedef std::set Instantiations; - Instantiations _instantiations; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - - virtual SubType get_subtype() const; - - virtual CPPInstance *as_instance(); - virtual CPPClassTemplateParameter *as_class_template_parameter(); - virtual CPPTypedefType *as_typedef_type(); - virtual CPPTypeDeclaration *as_type_declaration(); - virtual CPPExpression *as_expression(); - virtual CPPType *as_type(); - virtual CPPNamespace *as_namespace(); - virtual CPPUsing *as_using(); - virtual CPPSimpleType *as_simple_type(); - virtual CPPPointerType *as_pointer_type(); - virtual CPPReferenceType *as_reference_type(); - virtual CPPArrayType *as_array_type(); - virtual CPPConstType *as_const_type(); - virtual CPPFunctionType *as_function_type(); - virtual CPPFunctionGroup *as_function_group(); - virtual CPPExtensionType *as_extension_type(); - virtual CPPStructType *as_struct_type(); - virtual CPPEnumType *as_enum_type(); - virtual CPPTBDType *as_tbd_type(); - virtual CPPTypeProxy *as_type_proxy(); - virtual CPPMakeProperty *as_make_property(); - virtual CPPMakeSeq *as_make_seq(); - virtual CPPClosureType *as_closure_type(); - - inline const CPPInstance *as_instance() const { - return ((CPPDeclaration *)this)->as_instance(); - } - inline const CPPClassTemplateParameter *as_class_template_parameter() const { - return ((CPPDeclaration *)this)->as_class_template_parameter(); - } - inline const CPPTypedefType *as_typedef_type() const { - return ((CPPDeclaration *)this)->as_typedef_type(); - } - inline const CPPTypeDeclaration *as_type_declaration() const { - return ((CPPDeclaration *)this)->as_type_declaration(); - } - inline const CPPExpression *as_expression() const { - return ((CPPDeclaration *)this)->as_expression(); - } - inline const CPPType *as_type() const { - return ((CPPDeclaration *)this)->as_type(); - } - inline const CPPNamespace *as_namespace() const { - return ((CPPDeclaration *)this)->as_namespace(); - } - inline const CPPUsing *as_using() const { - return ((CPPDeclaration *)this)->as_using(); - } - inline const CPPSimpleType *as_simple_type() const { - return ((CPPDeclaration *)this)->as_simple_type(); - } - inline const CPPPointerType *as_pointer_type() const { - return ((CPPDeclaration *)this)->as_pointer_type(); - } - inline const CPPReferenceType *as_reference_type() const { - return ((CPPDeclaration *)this)->as_reference_type(); - } - inline const CPPArrayType *as_array_type() const { - return ((CPPDeclaration *)this)->as_array_type(); - } - inline const CPPConstType *as_const_type() const { - return ((CPPDeclaration *)this)->as_const_type(); - } - inline const CPPFunctionType *as_function_type() const { - return ((CPPDeclaration *)this)->as_function_type(); - } - inline const CPPFunctionGroup *as_function_group() const { - return ((CPPDeclaration *)this)->as_function_group(); - } - inline const CPPExtensionType *as_extension_type() const { - return ((CPPDeclaration *)this)->as_extension_type(); - } - inline const CPPStructType *as_struct_type() const { - return ((CPPDeclaration *)this)->as_struct_type(); - } - inline const CPPEnumType *as_enum_type() const { - return ((CPPDeclaration *)this)->as_enum_type(); - } - inline const CPPTBDType *as_tbd_type() const { - return ((CPPDeclaration *)this)->as_tbd_type(); - } - inline const CPPTypeProxy *as_type_proxy() const { - return ((CPPDeclaration *)this)->as_type_proxy(); - } - inline const CPPMakeProperty *as_make_property() const { - return ((CPPDeclaration *)this)->as_make_property(); - } - inline const CPPMakeSeq *as_make_seq() const { - return ((CPPDeclaration *)this)->as_make_seq(); - } - inline const CPPClosureType *as_closure_type() const { - return ((CPPDeclaration *)this)->as_closure_type(); - } - - CPPVisibility _vis; - CPPTemplateScope *_template_scope; - CPPFile _file; - CPPCommentBlock *_leading_comment; - CPPAttributeList _attributes; - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPDeclaration &decl) { - decl.output(out, 0, nullptr, false); - return out; -} - -std::ostream & -operator << (std::ostream &out, const CPPDeclaration::SubstDecl &decl); - -#endif diff --git a/dtool/src/cppparser/cppEnumType.cxx b/dtool/src/cppparser/cppEnumType.cxx deleted file mode 100644 index 1e0e133cad..0000000000 --- a/dtool/src/cppparser/cppEnumType.cxx +++ /dev/null @@ -1,328 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppEnumType.cxx - * @author drose - * @date 1999-10-25 - */ - -#include "cppEnumType.h" -#include "cppTypedefType.h" -#include "cppExpression.h" -#include "cppSimpleType.h" -#include "cppConstType.h" -#include "cppScope.h" -#include "cppParser.h" -#include "cppIdentifier.h" -#include "indent.h" - -/** - * Creates an untyped enum. - */ -CPPEnumType:: -CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope, - CPPScope *scope, const CPPFile &file, CPPAttributeList attr) : - CPPExtensionType(type, ident, current_scope, file, std::move(attr)), - _scope(scope), - _element_type(nullptr), - _last_value(nullptr) -{ - _parent_scope = (type == T_enum) ? current_scope : scope; - - if (ident != nullptr) { - ident->_native_scope = current_scope; - } -} - -/** - * Creates a typed enum. - */ -CPPEnumType:: -CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type, - CPPScope *current_scope, CPPScope *scope, const CPPFile &file, - CPPAttributeList attr) : - CPPExtensionType(type, ident, current_scope, file, std::move(attr)), - _scope(scope), - _element_type(element_type), - _last_value(nullptr) -{ - _parent_scope = (type == T_enum) ? current_scope : scope; - if (ident != nullptr) { - ident->_native_scope = current_scope; - } -} - -/** - * Returns true if this is a scoped enum. - */ -bool CPPEnumType:: -is_scoped() const { - return (_type != T_enum); -} - -/** - * Returns the integral type used to store enum values. - */ -CPPType *CPPEnumType:: -get_underlying_type() { - if (_element_type == nullptr) { - // This enum is untyped. Use a suitable default, ie. 'int'. In the - // future, we might want to check whether it fits in an int. - static CPPType *default_element_type = nullptr; - if (default_element_type == nullptr) { - default_element_type = - CPPType::new_type(new CPPConstType(new CPPSimpleType(CPPSimpleType::T_int, 0))); - } - - return default_element_type; - } else { - // This enum has an explicit type, so use that. - return CPPType::new_type(new CPPConstType(_element_type)); - } -} - -/** - * - */ -CPPInstance *CPPEnumType:: -add_element(const std::string &name, CPPExpression *value, - CPPPreprocessor *preprocessor, const cppyyltype &pos, - CPPAttributeList attr) { - CPPIdentifier *ident = new CPPIdentifier(name); - ident->_native_scope = _parent_scope; - - CPPInstance *inst; - if (_type == T_enum) { - // Weakly typed enum. - inst = new CPPInstance(get_underlying_type(), ident); - } else { - // C++11-style strongly typed enum. - inst = new CPPInstance(this, ident); - } - inst->_storage_class |= CPPInstance::SC_constexpr; - inst->_attributes = std::move(attr); - _elements.push_back(inst); - - if (value == nullptr) { - if (_last_value == nullptr) { - // This is the first value, and should therefore be 0. - static CPPExpression *const zero = new CPPExpression(0); - value = zero; - - } else if (_last_value->_type == CPPExpression::T_integer) { - value = new CPPExpression(_last_value->_u._integer + 1); - - } else if (_last_value->_type == CPPExpression::T_binary_operation && - _last_value->_u._op._operator == '+' && - _last_value->_u._op._op2->_type == CPPExpression::T_integer) { - // Prevent an endless expansion of + expressions. - value = new CPPExpression('+', - _last_value->_u._op._op1, - new CPPExpression(_last_value->_u._op._op2->_u._integer + 1)); - - } else { - // We may not be able to determine the value just yet. No problem; - // we'll just define it as another expression. - static CPPExpression *const one = new CPPExpression(1); - value = new CPPExpression('+', _last_value, one); - } - } - inst->_initializer = value; - _last_value = value; - - if (preprocessor != nullptr) { - // Same-line comment? - CPPCommentBlock *comment = - preprocessor->get_comment_on(pos.first_line, pos.file); - - if (comment == nullptr) { - // Nope. Check for a comment before this line. - comment = - preprocessor->get_comment_before(pos.first_line, pos.file); - - if (comment != nullptr) { - // This is a bit of a hack, but it prevents us from picking up a same- - // line comment from the previous line. - if (comment->_line_number != pos.first_line - 1 || - comment->_col_number <= pos.first_column) { - - inst->_leading_comment = comment; - } - } - } else { - inst->_leading_comment = comment; - } - } - - // Add the value to the enum scope (as per C++11), assuming it's not anonymous. - if (_scope != nullptr) { - _scope->add_enum_value(inst); - } - - // Now add it to the containing scope as well if it's not an "enum class". - if (!is_scoped() && _parent_scope != nullptr) { - _parent_scope->add_enum_value(inst); - } - - return inst; -} - -/** - * Returns true if the type has not yet been fully specified, false if it has. - */ -bool CPPEnumType:: -is_incomplete() const { - return false; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPEnumType:: -is_fully_specified() const { - if (!CPPDeclaration::is_fully_specified()) { - return false; - } - - if (_ident != nullptr && !_ident->is_fully_specified()) { - return false; - } - - if (_element_type != nullptr && !_element_type->is_fully_specified()) { - return false; - } - - Elements::const_iterator ei; - for (ei = _elements.begin(); ei != _elements.end(); ++ei) { - if (!(*ei)->is_fully_specified()) { - return false; - } - } - - return true; -} - -/** - * - */ -CPPDeclaration *CPPEnumType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPEnumType *rep = new CPPEnumType(*this); - - if (_ident != nullptr) { - rep->_ident = - _ident->substitute_decl(subst, current_scope, global_scope); - } - - if (_element_type != nullptr) { - rep->_element_type = - _element_type->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - } - - bool any_changed = false; - - for (size_t i = 0; i < _elements.size(); ++i) { - // We don't just do substitute_decl on the instance, which could lead to - // an infinite recursion. - CPPInstance *element = _elements[i]; - CPPExpression *value = element->_initializer-> - substitute_decl(subst, current_scope, global_scope)->as_expression(); - - if (is_scoped()) { - // For a strong enum, we consider the elements to be of this type. - if (value != element->_initializer) { - rep->_elements[i] = new CPPInstance(rep, element->_ident); - rep->_elements[i]->_initializer = value; - any_changed = true; - } - } else if (value != element->_initializer || - rep->get_underlying_type() != get_underlying_type()) { - // In an unscoped enum, the elements are integers. - rep->_elements[i] = new CPPInstance(rep->get_underlying_type(), element->_ident); - rep->_elements[i]->_initializer = value; - any_changed = true; - } - } - - if (rep->_ident == _ident && - rep->_element_type == _element_type && - !any_changed) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_enum_type(); - subst.insert(SubstDecl::value_type(this, rep)); - - return rep; -} - -/** - * - */ -void CPPEnumType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (!complete && _ident != nullptr) { - // If we have a name, use it. - if (cppparser_output_class_keyword) { - out << _type << " "; - } - out << _ident->get_local_name(scope); - } - else { - out << _type; - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - if (_ident != nullptr) { - out << " " << _ident->get_local_name(scope); - } - if (_element_type != nullptr) { - out << " : " << _element_type->get_local_name(scope); - } - - out << " {\n"; - for (CPPInstance *element : _elements) { - indent(out, indent_level + 2) << element->get_local_name(); - - if (!element->_attributes.is_empty()) { - out << " " << element->_attributes; - } - - if (element->_initializer != nullptr) { - out << " = " << *element->_initializer; - } - out << ",\n"; - } - indent(out, indent_level) << "}"; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPEnumType:: -get_subtype() const { - return ST_enum; -} - -/** - * - */ -CPPEnumType *CPPEnumType:: -as_enum_type() { - return this; -} diff --git a/dtool/src/cppparser/cppEnumType.h b/dtool/src/cppparser/cppEnumType.h deleted file mode 100644 index f2be4891c4..0000000000 --- a/dtool/src/cppparser/cppEnumType.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppEnumType.h - * @author drose - * @date 1999-10-25 - */ - -#ifndef CPPENUMTYPE_H -#define CPPENUMTYPE_H - -#include "dtoolbase.h" - -#include "cppBisonDefs.h" -#include "cppExtensionType.h" - -#include - -class CPPExpression; -class CPPInstance; -class CPPScope; - - -/** - * - */ -class CPPEnumType : public CPPExtensionType { -public: - CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope, - CPPScope *scope, const CPPFile &file, - CPPAttributeList attr = CPPAttributeList()); - CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type, - CPPScope *current_scope, CPPScope *scope, const CPPFile &file, - CPPAttributeList attr = CPPAttributeList()); - - bool is_scoped() const; - CPPType *get_underlying_type(); - - CPPInstance *add_element(const std::string &name, CPPExpression *value, - CPPPreprocessor *preprocessor, const cppyyltype &pos, - CPPAttributeList attr = CPPAttributeList()); - - virtual bool is_incomplete() const; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPEnumType *as_enum_type(); - - CPPScope *_parent_scope; - CPPScope *_scope; - CPPType *_element_type; - - typedef std::vector Elements; - Elements _elements; - CPPExpression *_last_value; -}; - - -#endif diff --git a/dtool/src/cppparser/cppExpression.cxx b/dtool/src/cppparser/cppExpression.cxx deleted file mode 100644 index 21797c76f7..0000000000 --- a/dtool/src/cppparser/cppExpression.cxx +++ /dev/null @@ -1,2450 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppExpression.cxx - * @author drose - * @date 1999-10-25 - */ - -#include "cppExpression.h" -#include "cppToken.h" -#include "cppIdentifier.h" -#include "cppType.h" -#include "cppSimpleType.h" -#include "cppPointerType.h" -#include "cppEnumType.h" -#include "cppConstType.h" -#include "cppArrayType.h" -#include "cppPreprocessor.h" -#include "cppInstance.h" -#include "cppFunctionGroup.h" -#include "cppFunctionType.h" -#include "cppClosureType.h" -#include "cppReferenceType.h" -#include "cppStructType.h" -#include "cppBison.h" -#include "pdtoa.h" - -#include - -using std::cerr; -using std::string; - -/** - * - */ -CPPExpression::Result:: -Result() { - _type = RT_error; -} - -/** - * - */ -CPPExpression::Result:: -Result(int value) { - _type = RT_integer; - _u._integer = value; -} - -/** - * - */ -CPPExpression::Result:: -Result(double value) { - _type = RT_real; - _u._real = value; -} - -/** - * - */ -CPPExpression::Result:: -Result(void *value) { - _type = RT_pointer; - _u._pointer = value; -} - - -/** - * - */ -int CPPExpression::Result:: -as_integer() const { - switch (_type) { - case RT_integer: - return _u._integer; - - case RT_real: - return (int)_u._real; - - case RT_pointer: - // We don't mind if this loses precision. - return (int)(intptr_t)(_u._pointer); - - default: - cerr << "Invalid type\n"; - assert(false); - return 0; - } -} - -/** - * - */ -double CPPExpression::Result:: -as_real() const { - switch (_type) { - case RT_integer: - return (double)_u._integer; - - case RT_real: - return _u._real; - - case RT_pointer: - // We don't mind if this loses precision. - return (double)(uintptr_t)(_u._pointer); - - default: - cerr << "Invalid type\n"; - assert(false); - return 0.0; - } -} - -/** - * - */ -void *CPPExpression::Result:: -as_pointer() const { - switch (_type) { - case RT_integer: - return (void *)(intptr_t)_u._integer; - - case RT_real: - return (void *)(uintptr_t)_u._real; - - case RT_pointer: - return _u._pointer; - - default: - cerr << "Invalid type\n"; - assert(false); - return nullptr; - } -} - -/** - * - */ -bool CPPExpression::Result:: -as_boolean() const { - switch (_type) { - case RT_integer: - return (_u._integer != 0); - - case RT_real: - return (_u._real != 0.0); - - case RT_pointer: - return (_u._pointer != nullptr); - - default: - cerr << "Invalid type\n"; - assert(false); - return false; - } -} - -/** - * - */ -void CPPExpression::Result:: -output(std::ostream &out) const { - switch (_type) { - case RT_integer: - out << _u._integer; - break; - - case RT_real: - out << _u._real; - break; - - case RT_pointer: - out << _u._pointer; - break; - - case RT_error: - out << "(error)"; - break; - - default: - out << "(**invalid type**)\n"; - } -} - -/** - * - */ -CPPExpression:: -CPPExpression(bool value) : - CPPDeclaration(CPPFile()) -{ - _type = T_boolean; - _u._boolean = value; -} - -/** - * - */ -CPPExpression:: -CPPExpression(unsigned long long value) : - CPPDeclaration(CPPFile()) -{ - _type = T_integer; - _u._integer = value; -} - -/** - * - */ -CPPExpression:: -CPPExpression(int value) : - CPPDeclaration(CPPFile()) -{ - _type = T_integer; - _u._integer = value; -} - -/** - * - */ -CPPExpression:: -CPPExpression(long double value) : - CPPDeclaration(CPPFile()) -{ - _type = T_real; - _u._real = value; -} - -/** - * - */ -CPPExpression:: -CPPExpression(const string &value) : - CPPDeclaration(CPPFile()) -{ - _type = T_string; - _str = value; -} - -/** - * - */ -CPPExpression:: -CPPExpression(CPPIdentifier *ident, CPPScope *current_scope, - CPPScope *global_scope, CPPPreprocessor *error_sink) : - CPPDeclaration(CPPFile()) -{ - CPPDeclaration *decl = - ident->find_symbol(current_scope, global_scope); - - if (decl != nullptr) { - CPPInstance *inst = decl->as_instance(); - if (inst != nullptr) { - _type = T_variable; - _u._variable = inst; - return; - } - /*CPPFunctionGroup *fgroup = decl->as_function_group(); - if (fgroup != nullptr) { - _type = T_function; - _u._fgroup = fgroup; - return; - }*/ - } - - _type = T_unknown_ident; - _u._ident = ident; - // _u._ident->_native_scope = current_scope; -} - -/** - * - */ -CPPExpression:: -CPPExpression(int unary_operator, CPPExpression *op1) : - CPPDeclaration(CPPFile()) -{ - _type = T_unary_operation; - _u._op._operator = unary_operator; - _u._op._op1 = op1; - _u._op._op2 = nullptr; - _u._op._op3 = nullptr; -} - -/** - * - */ -CPPExpression:: -CPPExpression(int binary_operator, CPPExpression *op1, CPPExpression *op2) : - CPPDeclaration(CPPFile()) -{ - _type = T_binary_operation; - _u._op._operator = binary_operator; - _u._op._op1 = op1; - _u._op._op2 = op2; - _u._op._op3 = nullptr; -} - -/** - * - */ -CPPExpression:: -CPPExpression(int trinary_operator, CPPExpression *op1, CPPExpression *op2, - CPPExpression *op3) : - CPPDeclaration(CPPFile()) -{ - _type = T_trinary_operation; - _u._op._operator = trinary_operator; - _u._op._op1 = op1; - _u._op._op2 = op2; - _u._op._op3 = op3; -} - -/** - * Creates an expression that represents a typecast operation. - */ -CPPExpression CPPExpression:: -typecast_op(CPPType *type, CPPExpression *op1, Type cast_type) { - assert(cast_type >= T_typecast && cast_type <= T_reinterpret_cast); - CPPExpression expr(0); - expr._type = cast_type; - expr._u._typecast._to = type; - expr._u._typecast._op1 = op1; - return expr; -} - -/** - * Creates an expression that represents a constructor call. - */ -CPPExpression CPPExpression:: -construct_op(CPPType *type, CPPExpression *op1) { - CPPExpression expr(0); - if (op1 == nullptr) { - // A default constructor call--no parameters. - expr._type = T_default_construct; - expr._u._typecast._to = type; - expr._u._typecast._op1 = nullptr; - } else { - // A normal constructor call, with parameters. - expr._type = T_construct; - expr._u._typecast._to = type; - expr._u._typecast._op1 = op1; - } - return expr; -} - -/** - * Creates an expression that represents an aggregate initialization. - */ -CPPExpression CPPExpression:: -aggregate_init_op(CPPType *type, CPPExpression *op1) { - CPPExpression expr(0); - if (op1 == nullptr) { - expr._type = T_empty_aggregate_init; - } else { - expr._type = T_aggregate_init; - } - expr._u._typecast._to = type; - expr._u._typecast._op1 = op1; - return expr; -} - -/** - * Creates an expression that represents a use of the new operator. - */ -CPPExpression CPPExpression:: -new_op(CPPType *type, CPPExpression *op1) { - CPPExpression expr(0); - if (op1 == nullptr) { - // A default new operation--no parameters. - expr._type = T_default_new; - expr._u._typecast._to = type; - expr._u._typecast._op1 = nullptr; - } else { - // A normal new operation, with parameters. - expr._type = T_new; - expr._u._typecast._to = type; - expr._u._typecast._op1 = op1; - } - return expr; -} - -/** - * Creates an expression that represents a use of the typeid operator. - */ -CPPExpression CPPExpression:: -typeid_op(CPPType *type, CPPType *std_type_info) { - CPPExpression expr(0); - expr._type = T_typeid_type; - expr._u._typeid._type = type; - expr._u._typeid._std_type_info = std_type_info; - return expr; -} - -/** - * Creates an expression that represents a use of the typeid operator. - */ -CPPExpression CPPExpression:: -typeid_op(CPPExpression *op1, CPPType *std_type_info) { - CPPExpression expr(0); - expr._type = T_typeid_expr; - expr._u._typeid._expr = op1; - expr._u._typeid._std_type_info = std_type_info; - return expr; -} - -/** - * Creates an expression that returns a particular type trait. - */ -CPPExpression CPPExpression:: -type_trait(int trait, CPPType *type, CPPType *arg) { - CPPExpression expr(0); - expr._type = T_type_trait; - expr._u._type_trait._trait = trait; - expr._u._type_trait._type = type; - expr._u._type_trait._arg = arg; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -sizeof_func(CPPType *type) { - CPPExpression expr(0); - expr._type = T_sizeof_type; - expr._u._typecast._to = type; - expr._u._typecast._op1 = nullptr; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -sizeof_func(CPPExpression *op1) { - CPPExpression expr(0); - expr._type = T_sizeof_expr; - expr._u._typecast._to = nullptr; - expr._u._typecast._op1 = op1; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -sizeof_ellipsis_func(CPPIdentifier *ident) { - CPPExpression expr(0); - expr._type = T_sizeof_ellipsis; - expr._u._ident = ident; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -alignof_func(CPPType *type) { - CPPExpression expr(0); - expr._type = T_alignof; - expr._u._typecast._to = type; - expr._u._typecast._op1 = nullptr; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -lambda(CPPClosureType *type) { - CPPExpression expr(0); - expr._type = T_lambda; - expr._u._closure_type = type; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -literal(unsigned long long value, CPPInstance *lit_op) { - CPPExpression expr(0); - expr._type = T_literal; - expr._u._literal._value = new CPPExpression(value); - expr._u._literal._operator = lit_op; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -literal(long double value, CPPInstance *lit_op) { - CPPExpression expr(0); - expr._type = T_literal; - expr._u._literal._value = new CPPExpression(value); - expr._u._literal._operator = lit_op; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -literal(CPPExpression *value, CPPInstance *lit_op) { - CPPExpression expr(0); - expr._type = T_literal; - expr._u._literal._value = value; - expr._u._literal._operator = lit_op; - return expr; -} - -/** - * - */ -CPPExpression CPPExpression:: -raw_literal(const string &raw, CPPInstance *lit_op) { - CPPExpression expr(0); - expr._type = T_raw_literal; - expr._str = raw; - expr._u._literal._value = nullptr; - expr._u._literal._operator = lit_op; - return expr; -} - -/** - * - */ -const CPPExpression &CPPExpression:: -get_nullptr() { - static CPPExpression expr(0); - expr._type = T_nullptr; - return expr; -} - -/** - * - */ -const CPPExpression &CPPExpression:: -get_default() { - static CPPExpression expr(0); - expr._type = T_default; - return expr; -} - -/** - * - */ -const CPPExpression &CPPExpression:: -get_delete() { - static CPPExpression expr(0); - expr._type = T_delete; - return expr; -} - -/** - * - */ -CPPExpression::Result CPPExpression:: -evaluate() const { - Result r1, r2; - - switch (_type) { - case T_nullptr: - return Result(nullptr); - - case T_boolean: - return Result((int)_u._boolean); - - case T_integer: - return Result((int)_u._integer); - - case T_real: - return Result((double)_u._real); - - case T_string: - case T_wstring: - case T_u8string: - case T_u16string: - case T_u32string: - return Result(); - - case T_variable: - if (_u._variable->_type != nullptr && - _u._variable->_initializer != nullptr) { - // A constexpr variable, which is treated as const. - if (_u._variable->_storage_class & (CPPInstance::SC_constexpr | CPPInstance::SC_constinit)) { - return _u._variable->_initializer->evaluate(); - } - // A const variable. Fetch its assigned value. - CPPConstType *const_type = _u._variable->_type->as_const_type(); - if (const_type != nullptr) { - return _u._variable->_initializer->evaluate(); - } - } - return Result(); - - case T_function: - return Result(); - - case T_unknown_ident: - return Result(); - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - assert(_u._typecast._op1 != nullptr); - r1 = _u._typecast._op1->evaluate(); - if (r1._type != RT_error) { - CPPSimpleType *stype = _u._typecast._to->as_simple_type(); - if (stype != nullptr) { - if (stype->_type == CPPSimpleType::T_bool) { - return Result(r1.as_boolean()); - - } else if (stype->_type == CPPSimpleType::T_int) { - return Result(r1.as_integer()); - - } else if (stype->_type == CPPSimpleType::T_float || - stype->_type == CPPSimpleType::T_double) { - return Result(r1.as_real()); - } - } - if (_u._typecast._to->as_pointer_type()) { - return Result(r1.as_pointer()); - } - } - return Result(); - - case T_construct: - case T_default_construct: - case T_aggregate_init: - case T_empty_aggregate_init: - case T_new: - case T_default_new: - case T_sizeof_type: - case T_sizeof_expr: - case T_sizeof_ellipsis: - return Result(); - - case T_alignof: - if (_u._typecast._to != nullptr) { - // Check if the type is defined with an alignas. TODO: this should - // probably be moved to a virtual getter on CPPType. - CPPExtensionType *etype = _u._typecast._to->as_extension_type(); - if (etype != nullptr && etype->_alignment != nullptr) { - return etype->_alignment->evaluate(); - } - } - return Result(); - - case T_binary_operation: - assert(_u._op._op2 != nullptr); - r2 = _u._op._op2->evaluate(); - - // The operators && and || are special cases: these are shirt-circuiting - // operators. Thus, if we are using either of these it might be - // acceptable for the second operand to be invalid, since we might never - // evaluate it. - - // In all other cases, both operands must be valid in order for the - // operation to be valid. - if (r2._type == RT_error && - (_u._op._operator != OROR && _u._op._operator != ANDAND)) { - return r2; - } - // Fall through - - - case T_trinary_operation: - // The trinary operator is also a short-circuiting operator: we don't test - // the second or third operands until we need them. The only critical one - // is the first operand. - - // Fall through - - case T_unary_operation: - assert(_u._op._op1 != nullptr); - r1 = _u._op._op1->evaluate(); - if (r1._type == RT_error) { - // Here's one more special case: if the first operand is invalid, it - // really means we don't know how to evaluate it. However, if the - // operator is ||, then it might not matter as long as we can evaluate - // the second one *and* that comes out to be true. - if (_u._op._operator == OROR && r2._type == RT_integer && - r2.as_boolean()) { - return r2; - } - - // Ditto for the operator being && and the second one coming out false. - if (_u._op._operator == ANDAND && r2._type == RT_integer && - !r2.as_boolean()) { - return r2; - } - - // Also for the operator being [] and the operand being a string. - if (_u._op._operator == '[' && r2._type == RT_integer && - (_u._op._op1->_type == T_string || - _u._op._op1->_type == T_u8string)) { - - int index = (int)r2.as_integer(); - if ((size_t)index == _u._op._op1->_str.size()) { - return Result(0); - } else if (index >= 0 && (size_t)index < _u._op._op1->_str.size()) { - return Result(_u._op._op1->_str[(size_t)index]); - } else { - cerr << "array index " << index << " out of bounds of string literal " - << *_u._op._op1 << "\n"; - } - } - - return r1; - } - - switch (_u._op._operator) { - case UNARY_NOT: - return Result(!r1.as_boolean()); - - case UNARY_NEGATE: - return Result(~r1.as_integer()); - - case UNARY_MINUS: - return (r1._type == RT_real) ? Result(-r1.as_real()) : Result(-r1.as_integer()); - - case UNARY_PLUS: - return r1; - - case UNARY_STAR: - case UNARY_REF: - return Result(); - - case '*': - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() * r2.as_real()); - } else { - return Result(r1.as_integer() * r2.as_integer()); - } - - case '/': - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() / r2.as_real()); - } else { - return Result(r1.as_integer() / r2.as_integer()); - } - - case '%': - return Result(r1.as_integer() % r2.as_integer()); - - case '+': - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() + r2.as_real()); - } else { - return Result(r1.as_integer() + r2.as_integer()); - } - - case '-': - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() - r2.as_real()); - } else { - return Result(r1.as_integer() - r2.as_integer()); - } - - case '|': - return Result(r1.as_integer() | r2.as_integer()); - - case '&': - return Result(r1.as_integer() & r2.as_integer()); - - case OROR: - if (r1.as_boolean()) { - return r1; - } else { - return r2; - } - - case ANDAND: - if (r1.as_boolean()) { - return r2; - } else { - return r1; - } - - case EQCOMPARE: - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() == r2.as_real()); - } else { - return Result(r1.as_integer() == r2.as_integer()); - } - - case NECOMPARE: - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() != r2.as_real()); - } else { - return Result(r1.as_integer() != r2.as_integer()); - } - - case LECOMPARE: - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() <= r2.as_real()); - } else { - return Result(r1.as_integer() <= r2.as_integer()); - } - - case GECOMPARE: - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() >= r2.as_real()); - } else { - return Result(r1.as_integer() >= r2.as_integer()); - } - - case SPACESHIP: - if (r1._type == RT_real || r2._type == RT_real) { - return Result((r1.as_real() > r2.as_real()) - (r1.as_real() < r2.as_real())); - } else { - return Result((r1.as_integer() > r2.as_integer()) - (r1.as_integer() < r2.as_integer())); - } - - case '<': - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() < r2.as_real()); - } else { - return Result(r1.as_integer() < r2.as_integer()); - } - - case '>': - if (r1._type == RT_real || r2._type == RT_real) { - return Result(r1.as_real() > r2.as_real()); - } else { - return Result(r1.as_integer() > r2.as_integer()); - } - - case LSHIFT: - return Result(r1.as_integer() << r2.as_integer()); - - case RSHIFT: - return Result(r1.as_integer() >> r2.as_integer()); - - case '?': - return r1.as_integer() ? - _u._op._op2->evaluate() : _u._op._op3->evaluate(); - - case '.': - case POINTSAT: - return Result(); - - case '[': // Array element reference - return Result(); - - case 'f': // Function evaluation - return Result(); - - case ',': - return r2; - - case KW_NOEXCEPT: - return Result(); - - default: - cerr << "**unexpected operator**\n"; - abort(); - } - - case T_literal: - case T_raw_literal: - return Result(); - - case T_typeid_type: - case T_typeid_expr: - return Result(); - - case T_type_trait: - switch (_u._type_trait._trait) { - case KW_HAS_VIRTUAL_DESTRUCTOR: - { - CPPStructType *struct_type = _u._type_trait._type->as_struct_type(); - return Result(struct_type != nullptr && struct_type->has_virtual_destructor()); - } - - case KW_IS_ABSTRACT: - { - CPPStructType *struct_type = _u._type_trait._type->as_struct_type(); - return Result(struct_type != nullptr && struct_type->is_abstract()); - } - - case KW_IS_BASE_OF: - { - CPPStructType *struct_type1 = _u._type_trait._type->as_struct_type(); - CPPStructType *struct_type2 = _u._type_trait._arg->as_struct_type(); - return Result(struct_type1 != nullptr && struct_type2 != nullptr && struct_type1->is_base_of(struct_type2)); - } - - case KW_IS_CLASS: - { - CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type(); - return Result(ext_type != nullptr && ( - ext_type->_type == CPPExtensionType::T_class || - ext_type->_type == CPPExtensionType::T_struct)); - } - - case KW_IS_CONSTRUCTIBLE: - if (_u._type_trait._arg == nullptr) { - return Result(_u._type_trait._type->is_default_constructible()); - } else { - return Result(_u._type_trait._type->is_constructible(_u._type_trait._arg)); - } - - case KW_IS_CONVERTIBLE_TO: - assert(_u._type_trait._arg != nullptr); - return Result(_u._type_trait._type->is_convertible_to(_u._type_trait._arg)); - - case KW_IS_DESTRUCTIBLE: - return Result(_u._type_trait._type->is_destructible()); - - case KW_IS_EMPTY: - { - CPPStructType *struct_type = _u._type_trait._type->as_struct_type(); - return Result(struct_type != nullptr && struct_type->is_empty()); - } - - case KW_IS_ENUM: - return Result(_u._type_trait._type->is_enum()); - - case KW_IS_FINAL: - { - CPPStructType *struct_type = _u._type_trait._type->as_struct_type(); - return Result(struct_type != nullptr && struct_type->is_final()); - } - - case KW_IS_FUNDAMENTAL: - return Result(_u._type_trait._type->is_fundamental()); - - case KW_IS_POD: - return Result(_u._type_trait._type->is_trivial() && - _u._type_trait._type->is_standard_layout()); - - case KW_IS_POLYMORPHIC: - { - CPPStructType *struct_type = _u._type_trait._type->as_struct_type(); - return Result(struct_type != nullptr && struct_type->is_polymorphic()); - } - - case KW_IS_STANDARD_LAYOUT: - return Result(_u._type_trait._type->is_standard_layout()); - - case KW_IS_TRIVIAL: - return Result(_u._type_trait._type->is_trivial()); - - case KW_IS_TRIVIALLY_COPYABLE: - return Result(_u._type_trait._type->is_trivially_copyable()); - - case KW_IS_UNION: - { - CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type(); - return Result(ext_type != nullptr && - ext_type->_type == CPPExtensionType::T_union); - } - - default: - cerr << "**unexpected type trait**\n"; - abort(); - } - - default: - cerr << "**invalid operand**\n"; - abort(); - } - - return Result(); // Compiler kludge; can't get here. -} - -/** - * Returns the type of the expression, if it is known, or NULL if the type - * cannot be determined. - */ -CPPType *CPPExpression:: -determine_type() const { - CPPType *t1 = nullptr; - CPPType *t2 = nullptr; - - static CPPType *nullptr_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_nullptr)); - - static CPPType *int_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); - - static CPPType *unsigned_long_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, - CPPSimpleType::F_unsigned | - CPPSimpleType::F_long)); - - static CPPType *bool_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); - - static CPPType *float_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); - - static CPPType *char_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); - - static CPPType *wchar_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); - - static CPPType *char16_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t)); - - static CPPType *char32_type = - CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t)); - - static CPPType *char_str_type = CPPType::new_type( - new CPPPointerType(CPPType::new_type(new CPPConstType(char_type)))); - - static CPPType *wchar_str_type = CPPType::new_type( - new CPPPointerType(CPPType::new_type(new CPPConstType(wchar_type)))); - - static CPPType *char16_str_type = CPPType::new_type( - new CPPPointerType(CPPType::new_type(new CPPConstType(char16_type)))); - - static CPPType *char32_str_type = CPPType::new_type( - new CPPPointerType(CPPType::new_type(new CPPConstType(char32_type)))); - - switch (_type) { - case T_nullptr: - return nullptr_type; - - case T_boolean: - return bool_type; - - case T_integer: - return int_type; - - case T_real: - return float_type; - - case T_string: - return char_str_type; - - case T_wstring: - return wchar_str_type; - - case T_u8string: - return char_str_type; - - case T_u16string: - return char16_str_type; - - case T_u32string: - return char32_str_type; - - case T_variable: - return _u._variable->_type; - - case T_function: - if (_u._fgroup->get_return_type() == nullptr) { - // There are multiple functions by this name that have different return - // types. We could attempt to differentiate them based on the parameter - // list, but that's a lot of work. Let's just give up. - return nullptr; - } - return _u._fgroup->_instances.front()->_type; - - case T_unknown_ident: - return nullptr; - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - case T_construct: - case T_default_construct: - case T_aggregate_init: - case T_empty_aggregate_init: - return _u._typecast._to; - - case T_new: - case T_default_new: - return CPPType::new_type(new CPPPointerType(_u._typecast._to)); - - case T_sizeof_type: - case T_sizeof_expr: - case T_sizeof_ellipsis: - case T_alignof: - // Note: this should actually be size_t, but that is defined as a typedef - // in parser-inc. We could try to resolve it, but that's hacky. Eh, it's - // probably not worth the effort to get this right. - return unsigned_long_type; - - case T_binary_operation: - case T_trinary_operation: - assert(_u._op._op2 != nullptr); - t2 = _u._op._op2->determine_type(); - // Fall through - - case T_unary_operation: - assert(_u._op._op1 != nullptr); - t1 = _u._op._op1->determine_type(); - - switch (_u._op._operator) { - case UNARY_NOT: - return bool_type; - - case UNARY_NEGATE: - return int_type; - - case UNARY_MINUS: - case UNARY_PLUS: - if (t1 != nullptr) { - switch (t1->get_subtype()) { - case CPPDeclaration::ST_array: - // Decay into pointer. - return CPPType::new_type(new CPPPointerType(t1->as_array_type()->_element_type)); - - case CPPDeclaration::ST_enum: - // Convert into integral type. - return t1->as_enum_type()->get_underlying_type(); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = t1->as_simple_type(); - if ((simple_type->_flags & CPPSimpleType::F_short) != 0 || - simple_type->_type == CPPSimpleType::T_bool || - simple_type->_type == CPPSimpleType::T_wchar_t || - simple_type->_type == CPPSimpleType::T_char16_t) { - // Integer promotion. - return int_type; - } - } - // Fall through. - default: - return t1; - } - } - return nullptr; - - case UNARY_STAR: - case '[': // Array element reference - if (t1 != nullptr) { - if (t1->as_pointer_type()) { - return t1->as_pointer_type()->_pointing_at; - } - if (t1->as_array_type()) { - return t1->as_array_type()->_element_type; - } - } - return nullptr; - - case UNARY_REF: - return t1; - - case '*': - case '/': - case '+': - case '-': - if (t1 == nullptr) { - return t2; - } else if (t2 == nullptr) { - return t1; - } else if (t1->as_pointer_type()) { - if (t2->as_pointer_type()) { - return int_type; - } - return t1; - } - return elevate_type(t1, t2); - - case '%': - case '|': - case '&': - case LSHIFT: - case RSHIFT: - return int_type; - - case OROR: - case ANDAND: - case EQCOMPARE: - case NECOMPARE: - case LECOMPARE: - case GECOMPARE: - case '<': - case '>': - case KW_NOEXCEPT: - return bool_type; - - case SPACESHIP: - return nullptr; - - case '?': - return t2; - - case '.': - case POINTSAT: - return nullptr; - - case 'f': // Function evaluation - if (t1 != nullptr) { - // Easy case, function with only a single overload. - CPPFunctionType *ftype = t1->as_function_type(); - if (ftype != nullptr) { - return ftype->_return_type; - } - } else if (_u._op._op1->_type == T_function) { - CPPFunctionGroup *fgroup = _u._op._op1->_u._fgroup; - if (_u._op._op2 == nullptr) { - // If we are passing no args, look for an overload that has takes no - // args. - for (auto it = fgroup->_instances.begin(); it != fgroup->_instances.end(); ++it) { - CPPInstance *inst = *it; - if (inst != nullptr && inst->_type != nullptr) { - CPPFunctionType *type = inst->_type->as_function_type(); - if (type != nullptr && type->accepts_num_parameters(0)) { - return type->_return_type; - } - } - } - } else { - //TODO - } - } - return nullptr; - - case ',': - return t2; - - default: - cerr << "**unexpected operator**\n"; - abort(); - } - - case T_literal: - case T_raw_literal: - if (_u._literal._operator != nullptr) { - CPPType *type = _u._literal._operator->_type; - - CPPFunctionType *ftype = type->as_function_type(); - if (ftype != nullptr) { - return ftype->_return_type; - } - } - return nullptr; - - case T_typeid_type: - case T_typeid_expr: - return _u._typeid._std_type_info; - - case T_type_trait: - return bool_type; - - case T_lambda: - return _u._closure_type; - - default: - cerr << "**invalid operand**\n"; - abort(); - } - - return nullptr; // Compiler kludge; can't get here. -} - -/** - * Returns true if this is an lvalue expression. - */ -bool CPPExpression:: -is_lvalue() const { - switch (_type) { - case T_variable: - case T_function: - case T_unknown_ident: - return true; - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - { - CPPReferenceType *ref_type = _u._typecast._to->as_reference_type(); - return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue; - } - - case T_unary_operation: - if (_u._op._operator == 'f') { - // A function returning an lvalue reference. - CPPType *return_type = determine_type(); - if (return_type != nullptr) { - CPPReferenceType *ref_type = return_type->as_reference_type(); - return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue; - } - } - return _u._op._operator == PLUSPLUS - || _u._op._operator == MINUSMINUS - || _u._op._operator == '*'; - - case T_binary_operation: - if (_u._op._operator == ',') { - CPPReferenceType *ref_type = _u._op._op2->as_reference_type(); - return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue; - } - return (_u._op._operator == POINTSAT || _u._op._operator == ','); - - case T_trinary_operation: - return _u._op._op2->is_lvalue() && _u._op._op3->is_lvalue(); - - case T_literal: - case T_raw_literal: - return true; - - default: - break; - } - - return false; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPExpression:: -is_fully_specified() const { - if (!CPPDeclaration::is_fully_specified()) { - return false; - } - - switch (_type) { - case T_nullptr: - case T_boolean: - case T_integer: - case T_real: - case T_string: - case T_wstring: - case T_u8string: - case T_u16string: - case T_u32string: - return false; - - case T_variable: - return _u._variable->is_fully_specified(); - - case T_function: - return _u._fgroup->is_fully_specified(); - - case T_unknown_ident: - return _u._ident->is_fully_specified(); - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - case T_construct: - case T_aggregate_init: - case T_new: - return (_u._typecast._to->is_fully_specified() && - _u._typecast._op1->is_fully_specified()); - - case T_default_construct: - case T_empty_aggregate_init: - case T_default_new: - case T_sizeof_type: - case T_alignof: - return _u._typecast._to->is_fully_specified(); - - case T_sizeof_expr: - return _u._typecast._op1->is_fully_specified(); - - case T_sizeof_ellipsis: - return _u._ident->is_fully_specified(); - - case T_trinary_operation: - if (!_u._op._op3->is_fully_specified()) { - return false; - } - // Fall through - - case T_binary_operation: - if (!_u._op._op2->is_fully_specified()) { - return false; - } - // Fall through - - case T_unary_operation: - return _u._op._op1->is_fully_specified(); - - case T_literal: - return _u._literal._value->is_fully_specified() && - _u._literal._operator->is_fully_specified(); - - case T_raw_literal: - return _u._literal._value->is_fully_specified(); - - case T_typeid_type: - return _u._typeid._type->is_fully_specified(); - - case T_typeid_expr: - return _u._typeid._expr->is_fully_specified(); - - case T_type_trait: - return _u._type_trait._type->is_fully_specified(); - - case T_lambda: - return _u._closure_type->is_fully_specified(); - - default: - return true; - } -} - -/** - * - */ -CPPDeclaration *CPPExpression:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPDeclaration *top = - CPPDeclaration::substitute_decl(subst, current_scope, global_scope); - if (top != this) { - return top; - } - - CPPExpression *rep = new CPPExpression(*this); - bool any_changed = false; - CPPDeclaration *decl; - - switch (_type) { - case T_variable: - decl = _u._variable->substitute_decl(subst, current_scope, global_scope); - if (decl != rep->_u._variable) { - if (decl->as_instance()) { - // Replacing the variable reference with another variable reference. - rep->_u._variable = decl->as_instance(); - any_changed = true; - - } else if (decl->as_expression()) { - // Replacing the variable reference with an expression. - delete rep; - rep = decl->as_expression(); - any_changed = true; - } - } - break; - - case T_unknown_ident: - rep->_u._ident = _u._ident->substitute_decl(subst, current_scope, global_scope); - any_changed = any_changed || (rep->_u._ident != _u._ident); - - // See if we can define it now. - decl = rep->_u._ident->find_symbol(current_scope, global_scope, subst); - if (decl != nullptr) { - CPPInstance *inst = decl->as_instance(); - if (inst != nullptr) { - rep->_type = T_variable; - rep->_u._variable = inst; - any_changed = true; - - decl = inst->substitute_decl(subst, current_scope, global_scope); - if (decl != inst) { - if (decl->as_instance()) { - // Replacing the variable reference with another variable - // reference. - rep->_u._variable = decl->as_instance(); - - } else if (decl->as_expression()) { - // Replacing the variable reference with an expression. - delete rep; - rep = decl->as_expression(); - } - } - break; - } - CPPFunctionGroup *fgroup = decl->as_function_group(); - if (fgroup != nullptr) { - rep->_type = T_function; - rep->_u._fgroup = fgroup; - any_changed = true; - } - } - - break; - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - case T_construct: - case T_aggregate_init: - case T_new: - rep->_u._typecast._op1 = - _u._typecast._op1->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - any_changed = any_changed || (rep->_u._typecast._op1 != _u._typecast._op1); - // fall through - - case T_default_construct: - case T_empty_aggregate_init: - case T_default_new: - case T_sizeof_type: - case T_alignof: - rep->_u._typecast._to = - _u._typecast._to->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - any_changed = any_changed || (rep->_u._typecast._to != _u._typecast._to); - break; - - case T_sizeof_expr: - rep->_u._typecast._op1 = - _u._typecast._op1->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - any_changed = any_changed || (rep->_u._typecast._op1 != _u._typecast._op1); - break; - - case T_trinary_operation: - rep->_u._op._op3 = - _u._op._op3->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - any_changed = any_changed || (rep->_u._op._op3 != _u._op._op3); - // fall through - - case T_binary_operation: - rep->_u._op._op2 = - _u._op._op2->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - any_changed = any_changed || (rep->_u._op._op2 != _u._op._op2); - // fall through - - case T_unary_operation: - rep->_u._op._op1 = - _u._op._op1->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - any_changed = any_changed || (rep->_u._op._op1 != _u._op._op1); - break; - - case T_typeid_type: - rep->_u._typeid._type = - _u._typeid._type->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - any_changed = any_changed || (rep->_u._typeid._type != _u._typeid._type); - break; - - case T_typeid_expr: - rep->_u._typeid._expr = - _u._typeid._expr->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr); - break; - - case T_type_trait: - rep->_u._type_trait._type = - _u._type_trait._type->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - any_changed = any_changed || (rep->_u._type_trait._type != _u._type_trait._type); - break; - - default: - break; - } - - if (!any_changed) { - delete rep; - rep = this; - } - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - - -/** - * Returns true if any type within the expression list is a CPPTBDType and - * thus isn't fully determined right now. - */ -bool CPPExpression:: -is_tbd() const { - switch (_type) { - case T_variable: - if (_u._variable->_type != nullptr && - _u._variable->_initializer != nullptr) { - if (_u._variable->_storage_class & (CPPInstance::SC_constexpr | CPPInstance::SC_constinit)) { - return false; - } - CPPConstType *const_type = _u._variable->_type->as_const_type(); - if (const_type != nullptr) { - return false; - } - } - - return true; - - case T_unknown_ident: - return true; - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - case T_construct: - case T_aggregate_init: - case T_empty_aggregate_init: - case T_new: - case T_default_construct: - case T_default_new: - case T_sizeof_type: - case T_alignof: - return _u._typecast._to->is_tbd(); - - case T_sizeof_expr: - return _u._typecast._op1->is_tbd(); - - case T_trinary_operation: - if (_u._op._op3->is_tbd()) { - return true; - } - // fall through - - case T_binary_operation: - if (_u._op._op2->is_tbd()) { - return true; - } - // fall through - - case T_unary_operation: - if (_u._op._op1->is_tbd()) { - return true; - } - return false; - - case T_typeid_type: - return _u._typeid._type->is_tbd(); - - case T_typeid_expr: - return _u._typeid._expr->is_tbd(); - - case T_type_trait: - return _u._type_trait._type->is_tbd(); - - case T_lambda: - return _u._closure_type->is_tbd(); - - default: - return false; - } -} - -/** - * - */ -void CPPExpression:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool) const { - switch (_type) { - case T_nullptr: - out << "nullptr"; - break; - - case T_boolean: - out << (_u._boolean ? "true" : "false"); - break; - - case T_integer: - out << _u._integer; - break; - - case T_real: - { - // We use our own dtoa implementation here because it guarantees to - // never format the number as an integer. - char buffer[32]; - pdtoa(_u._real, buffer); - out << buffer; - } - break; - - case T_string: - case T_wstring: - case T_u8string: - case T_u16string: - case T_u32string: - { - switch (_type) { - case T_wstring: - out << 'L'; - break; - case T_u8string: - out << "u8"; - break; - case T_u16string: - out << "u"; - break; - case T_u32string: - out << "U"; - break; - default: - break; - } - // We don't really care about preserving the encoding for now. - out << '"'; - string::const_iterator si; - for (si = _str.begin(); si != _str.end(); ++si) { - switch (*si) { - case '\n': - out << "\\n"; - break; - - case '\t': - out << "\\t"; - break; - - case '\r': - out << "\\r"; - break; - - case '\a': - out << "\\a"; - break; - - case '"': - out << "\\\""; - break; - - case '\\': - out << "\\\\"; - break; - - default: - if (isprint(*si)) { - out << *si; - } else { - out << '\\' << std::oct << std::setw(3) << std::setfill('0') << (int)(*si) - << std::dec << std::setw(0); - } - } - } - } - out << '"'; - break; - - case T_variable: - // We can just refer to the variable by name, except if it's a private - // constant, in which case we have to compute the value, since we may have - // to use it in generated code. - if (_u._variable->_type != nullptr && - _u._variable->_initializer != nullptr && - _u._variable->_vis > V_public) { - // A constexpr or const variable. Fetch its assigned value. - CPPConstType *const_type = _u._variable->_type->as_const_type(); - if ((_u._variable->_storage_class & CPPInstance::SC_constexpr) != 0 || - const_type != nullptr) { - _u._variable->_initializer->output(out, indent_level, scope, false); - break; - } - } - _u._variable->_ident->output(out, scope); - break; - - case T_function: - // Pick any instance; they all have the same name anyway. - if (!_u._fgroup->_instances.empty() && _u._fgroup->_instances[0]->_ident != nullptr) { - _u._fgroup->_instances[0]->_ident->output(out, scope); - } else { - out << _u._fgroup->_name; - } - break; - - case T_unknown_ident: - _u._ident->output(out, scope); - break; - - case T_typecast: - out << "("; - _u._typecast._to->output(out, indent_level, scope, false); - out << ")("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_static_cast: - out << "static_cast<"; - _u._typecast._to->output(out, indent_level, scope, false); - out << ">("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_dynamic_cast: - out << "dynamic_cast<"; - _u._typecast._to->output(out, indent_level, scope, false); - out << ">("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_const_cast: - out << "const_cast<"; - _u._typecast._to->output(out, indent_level, scope, false); - out << ">("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_reinterpret_cast: - out << "reinterpret_cast<"; - _u._typecast._to->output(out, indent_level, scope, false); - out << ">("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_construct: - _u._typecast._to->output(out, indent_level, scope, false); - out << "("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_default_construct: - _u._typecast._to->output(out, indent_level, scope, false); - out << "()"; - break; - - case T_aggregate_init: - _u._typecast._to->output(out, indent_level, scope, false); - out << "{"; - _u._typecast._op1->output(out, indent_level, scope, false); - out << "}"; - break; - - case T_empty_aggregate_init: - _u._typecast._to->output(out, indent_level, scope, false); - out << "{}"; - break; - - case T_new: - out << "(new "; - _u._typecast._to->output(out, indent_level, scope, false); - out << "("; - _u._typecast._op1->output(out, indent_level, scope, false); - out << "))"; - break; - - case T_default_new: - out << "(new "; - _u._typecast._to->output(out, indent_level, scope, false); - out << "())"; - break; - - case T_sizeof_type: - out << "sizeof("; - _u._typecast._to->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_sizeof_expr: - out << "sizeof "; - _u._typecast._op1->output(out, indent_level, scope, false); - break; - - case T_sizeof_ellipsis: - out << "sizeof...("; - _u._ident->output(out, scope); - out << ")"; - break; - - case T_alignof: - out << "alignof("; - _u._typecast._to->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_unary_operation: - switch (_u._op._operator) { - case UNARY_NOT: - out << "(! "; - _u._op._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case UNARY_NEGATE: - out << "(~ "; - _u._op._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case UNARY_MINUS: - out << '-'; - _u._op._op1->output(out, indent_level, scope, false); - break; - - case UNARY_PLUS: - out << '+'; - _u._op._op1->output(out, indent_level, scope, false); - break; - - case UNARY_STAR: - out << "(* "; - _u._op._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case UNARY_REF: - out << "(& "; - _u._op._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - case 'f': // Function evaluation, no parameters. - _u._op._op1->output(out, indent_level, scope, false); - out << "()"; - break; - - case KW_NOEXCEPT: - out << "noexcept("; - _u._op._op1->output(out, indent_level, scope, false); - out << ")"; - break; - - default: - out << "(" << (char)_u._op._operator << " "; - _u._op._op1->output(out, indent_level, scope, false); - out << ")"; - break; - } - break; - - case T_binary_operation: - switch (_u._op._operator) { - case OROR: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " || "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case ANDAND: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " && "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case EQCOMPARE: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " == "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case NECOMPARE: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " != "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case LECOMPARE: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " <= "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case GECOMPARE: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " >= "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case SPACESHIP: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " <=> "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case LSHIFT: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " << "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case RSHIFT: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " >> "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - break; - - case '.': - _u._op._op1->output(out, indent_level, scope, false); - out << "."; - _u._op._op2->output(out, indent_level, scope, false); - break; - - case POINTSAT: - _u._op._op1->output(out, indent_level, scope, false); - out << "->"; - _u._op._op2->output(out, indent_level, scope, false); - break; - - case '[': // Array element reference - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << "["; - _u._op._op2->output(out, indent_level, scope, false); - out << "])"; - break; - - case 'f': // Function evaluation - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << "("; - _u._op._op2->output(out, indent_level, scope, false); - out << "))"; - break; - - case ',': // Comma, no parens are used - _u._op._op1->output(out, indent_level, scope, false); - out << ", "; - _u._op._op2->output(out, indent_level, scope, false); - break; - - default: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " " << (char)_u._op._operator << " "; - _u._op._op2->output(out, indent_level, scope, false); - out << ")"; - } - break; - - case T_trinary_operation: - out << "("; - _u._op._op1->output(out, indent_level, scope, false); - out << " ? "; - _u._op._op2->output(out, indent_level, scope, false); - out << " : "; - _u._op._op3->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_literal: - _u._literal._value->output(out, indent_level, scope, false); - if (_u._literal._operator != nullptr) { - string name = _u._literal._operator->get_simple_name(); - assert(name.substr(0, 12) == "operator \"\" "); - out << name.substr(12); - } - break; - - case T_raw_literal: - out << _str; - if (_u._literal._operator != nullptr) { - string name = _u._literal._operator->get_simple_name(); - assert(name.substr(0, 12) == "operator \"\" "); - out << name.substr(12); - } - break; - - case T_typeid_type: - out << "typeid("; - _u._typeid._type->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_typeid_expr: - out << "typeid("; - _u._typeid._expr->output(out, indent_level, scope, false); - out << ")"; - break; - - case T_default: - out << "default"; - break; - - case T_delete: - out << "delete"; - break; - - case T_type_trait: - switch (_u._type_trait._trait) { - case KW_HAS_VIRTUAL_DESTRUCTOR: - out << "__has_virtual_destructor"; - break; - case KW_IS_ABSTRACT: - out << "__is_abstract"; - break; - case KW_IS_BASE_OF: - out << "__is_base_of"; - break; - case KW_IS_CLASS: - out << "__is_class"; - break; - case KW_IS_CONSTRUCTIBLE: - out << "__is_constructible"; - break; - case KW_IS_CONVERTIBLE_TO: - out << "__is_convertible_to"; - break; - case KW_IS_DESTRUCTIBLE: - out << "__is_destructible"; - break; - case KW_IS_EMPTY: - out << "__is_empty"; - break; - case KW_IS_ENUM: - out << "__is_enum"; - break; - case KW_IS_FINAL: - out << "__is_final"; - break; - case KW_IS_FUNDAMENTAL: - out << "__is_fundamental"; - break; - case KW_IS_POD: - out << "__is_pod"; - break; - case KW_IS_POLYMORPHIC: - out << "__is_polymorphic"; - break; - case KW_IS_STANDARD_LAYOUT: - out << "__is_standard_layout"; - break; - case KW_IS_TRIVIAL: - out << "__is_trivial"; - break; - case KW_IS_TRIVIALLY_COPYABLE: - out << "__is_trivially_copyable"; - break; - case KW_IS_UNION: - out << "__is_union"; - break; - default: - out << (evaluate().as_boolean() ? "true" : "false"); - return; - } - out << '('; - _u._type_trait._type->output(out, indent_level, scope, false); - out << ')'; - break; - - case T_lambda: - _u._closure_type->output(out, indent_level, scope, false); - break; - - default: - out << "(** invalid operand type " << (int)_type << " **)"; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPExpression:: -get_subtype() const { - return ST_expression; -} - -/** - * - */ -CPPExpression *CPPExpression:: -as_expression() { - return this; -} - -/** - * Returns the most general of the two given types. - */ -CPPType *CPPExpression:: -elevate_type(CPPType *t1, CPPType *t2) { - CPPSimpleType *st1 = t1->as_simple_type(); - CPPSimpleType *st2 = t2->as_simple_type(); - - if (st1 == nullptr || st2 == nullptr) { - // Nothing we can do about this. Who knows? - return nullptr; - } - - if (st1->_type == st2->_type) { - // They have the same type, so return the one with the largest flag bits. - if (st1->_flags & CPPSimpleType::F_longlong) { - return st1; - } else if (st2->_flags & CPPSimpleType::F_longlong) { - return st2; - } else if (st1->_flags & CPPSimpleType::F_long) { - return st1; - } else if (st2->_flags & CPPSimpleType::F_long) { - return st2; - } else if (st1->_flags & CPPSimpleType::F_short) { - return st2; - } else if (st2->_flags & CPPSimpleType::F_short) { - return st1; - } - return st1; - } - - // They have different types. - if (st1->_type == CPPSimpleType::T_float || - st1->_type == CPPSimpleType::T_double) { - return st1; - } else if (st2->_type == CPPSimpleType::T_float || - st2->_type == CPPSimpleType::T_double) { - return st2; - } else if (st1->_type == CPPSimpleType::T_int) { - return st1; - } else if (st2->_type == CPPSimpleType::T_int) { - return st2; - } else if (st1->_type == CPPSimpleType::T_bool) { - return st1; - } else if (st2->_type == CPPSimpleType::T_bool) { - return st2; - } - return st1; -} - -/** - * Called by CPPDeclaration to determine whether this expr is equivalent to - * another expr. - */ -bool CPPExpression:: -is_equal(const CPPDeclaration *other) const { - const CPPExpression *ot = ((CPPDeclaration *)other)->as_expression(); - assert(ot != nullptr); - - if (_type != ot->_type) { - return false; - } - - switch (_type) { - case T_nullptr: - return true; - - case T_boolean: - return _u._boolean == ot->_u._boolean; - - case T_integer: - return _u._integer == ot->_u._integer; - - case T_real: - return _u._real == ot->_u._real; - - case T_string: - case T_wstring: - case T_u8string: - case T_u16string: - case T_u32string: - return _str == ot->_str; - - case T_variable: - return _u._variable == ot->_u._variable; - - case T_function: - return _u._fgroup == ot->_u._fgroup; - - case T_unknown_ident: - case T_sizeof_ellipsis: - return *_u._ident == *ot->_u._ident; - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - case T_construct: - case T_aggregate_init: - case T_new: - return _u._typecast._to == ot->_u._typecast._to && - *_u._typecast._op1 == *ot->_u._typecast._op1; - - case T_default_construct: - case T_empty_aggregate_init: - case T_default_new: - case T_sizeof_type: - case T_alignof: - return _u._typecast._to == ot->_u._typecast._to; - - case T_sizeof_expr: - return _u._typecast._op1 == ot->_u._typecast._op1; - - case T_unary_operation: - return *_u._op._op1 == *ot->_u._op._op1; - - case T_binary_operation: - return *_u._op._op1 == *ot->_u._op._op1 && - *_u._op._op2 == *ot->_u._op._op2; - - case T_trinary_operation: - return *_u._op._op1 == *ot->_u._op._op1 && - *_u._op._op2 == *ot->_u._op._op2; - - case T_literal: - return *_u._literal._value == *ot->_u._literal._value && - _u._literal._operator == ot->_u._literal._operator; - - case T_raw_literal: - return _str == ot->_str && - _u._literal._operator == ot->_u._literal._operator; - - case T_typeid_type: - return _u._typeid._type == ot->_u._typeid._type; - - case T_typeid_expr: - return _u._typeid._expr == ot->_u._typeid._expr; - - case T_type_trait: - return _u._type_trait._trait == ot->_u._type_trait._trait && - _u._type_trait._type == ot->_u._type_trait._type; - - case T_lambda: - return _u._closure_type == ot->_u._closure_type; - - default: - cerr << "(** invalid operand type " << (int)_type << " **)"; - } - - return true; -} - -/** - * Called by CPPDeclaration to determine whether this expr should be ordered - * before another expr of the same type, in an arbitrary but fixed ordering. - */ -bool CPPExpression:: -is_less(const CPPDeclaration *other) const { - const CPPExpression *ot = ((CPPDeclaration *)other)->as_expression(); - assert(ot != nullptr); - - if (_type != ot->_type) { - return (int)_type < (int)ot->_type; - } - - switch (_type) { - case T_nullptr: - return false; - - case T_boolean: - return _u._boolean < ot->_u._boolean; - - case T_integer: - return _u._integer < ot->_u._integer; - - case T_real: - return _u._real < ot->_u._real; - - case T_string: - case T_wstring: - case T_u8string: - case T_u16string: - case T_u32string: - return _str < ot->_str; - - case T_variable: - return _u._variable < ot->_u._variable; - - case T_function: - return *_u._fgroup < *ot->_u._fgroup; - - case T_unknown_ident: - case T_sizeof_ellipsis: - return *_u._ident < *ot->_u._ident; - - case T_typecast: - case T_static_cast: - case T_dynamic_cast: - case T_const_cast: - case T_reinterpret_cast: - case T_construct: - case T_aggregate_init: - case T_new: - if (_u._typecast._to != ot->_u._typecast._to) { - return _u._typecast._to < ot->_u._typecast._to; - } - return *_u._typecast._op1 < *ot->_u._typecast._op1; - - case T_default_construct: - case T_empty_aggregate_init: - case T_default_new: - case T_sizeof_type: - case T_alignof: - return _u._typecast._to < ot->_u._typecast._to; - - case T_sizeof_expr: - return _u._typecast._op1 < ot->_u._typecast._op1; - - case T_trinary_operation: - if (*_u._op._op3 != *ot->_u._op._op3) { - return *_u._op._op3 < *ot->_u._op._op3; - } - // Fall through - - case T_binary_operation: - if (*_u._op._op2 != *ot->_u._op._op2) { - return *_u._op._op2 < *ot->_u._op._op2; - } - // Fall through - - case T_unary_operation: - return *_u._op._op1 < *ot->_u._op._op1; - - case T_literal: - if (_u._literal._operator != ot->_u._literal._operator) { - return _u._literal._operator < ot->_u._literal._operator; - } - return *_u._literal._value < *ot->_u._literal._value; - - case T_raw_literal: - if (_u._literal._operator != ot->_u._literal._operator) { - return _u._literal._operator < ot->_u._literal._operator; - } - return _str < ot->_str; - - case T_typeid_type: - return _u._typeid._type < ot->_u._typeid._type; - - case T_typeid_expr: - return *_u._typeid._expr < *ot->_u._typeid._expr; - - case T_type_trait: - if (_u._type_trait._trait != ot->_u._type_trait._trait) { - return _u._type_trait._trait < ot->_u._type_trait._trait; - } - return *_u._type_trait._type < *ot->_u._type_trait._type; - - case T_lambda: - return _u._closure_type < ot->_u._closure_type; - - default: - cerr << "(** invalid operand type " << (int)_type << " **)"; - } - - return false; -} diff --git a/dtool/src/cppparser/cppExpression.h b/dtool/src/cppparser/cppExpression.h deleted file mode 100644 index cd6030f73d..0000000000 --- a/dtool/src/cppparser/cppExpression.h +++ /dev/null @@ -1,203 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppExpression.h - * @author drose - * @date 1999-10-25 - */ - -#ifndef CPPEXPRESSION_H -#define CPPEXPRESSION_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -class CPPIdentifier; -class CPPType; -class CPPPreprocessor; -class CPPFunctionGroup; - -/** - * - */ -class CPPExpression : public CPPDeclaration { -public: - enum Type { - T_nullptr, - T_boolean, - T_integer, - T_real, - T_string, - T_wstring, - T_u8string, - T_u16string, - T_u32string, - T_variable, - T_function, - T_unknown_ident, - T_typecast, - T_static_cast, - T_dynamic_cast, - T_const_cast, - T_reinterpret_cast, - T_construct, - T_default_construct, - T_aggregate_init, - T_empty_aggregate_init, - T_new, - T_default_new, - T_sizeof_type, - T_sizeof_expr, - T_sizeof_ellipsis, - T_alignof, - T_unary_operation, - T_binary_operation, - T_trinary_operation, - T_literal, - T_raw_literal, - T_typeid_type, - T_typeid_expr, - T_type_trait, - T_lambda, - - // These are used when parsing =default and =delete methods. - T_default, - T_delete, - }; - - CPPExpression(bool value); - CPPExpression(unsigned long long value); - CPPExpression(int value); - CPPExpression(const std::string &value); - CPPExpression(long double value); - CPPExpression(CPPIdentifier *ident, CPPScope *current_scope, - CPPScope *global_scope, CPPPreprocessor *error_sink = nullptr); - CPPExpression(int unary_operator, CPPExpression *op1); - CPPExpression(int binary_operator, CPPExpression *op1, CPPExpression *op2); - CPPExpression(int trinary_operator, CPPExpression *op1, CPPExpression *op2, CPPExpression *op3); - - static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast); - static CPPExpression construct_op(CPPType *type, CPPExpression *op1); - static CPPExpression aggregate_init_op(CPPType *type, CPPExpression *op1); - static CPPExpression new_op(CPPType *type, CPPExpression *op1 = nullptr); - static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info); - static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info); - static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = nullptr); - static CPPExpression sizeof_func(CPPType *type); - static CPPExpression sizeof_func(CPPExpression *op1); - static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident); - static CPPExpression alignof_func(CPPType *type); - static CPPExpression lambda(CPPClosureType *type); - - static CPPExpression literal(unsigned long long value, CPPInstance *lit_op); - static CPPExpression literal(long double value, CPPInstance *lit_op); - static CPPExpression literal(CPPExpression *value, CPPInstance *lit_op); - static CPPExpression raw_literal(const std::string &raw, CPPInstance *lit_op); - - static const CPPExpression &get_nullptr(); - static const CPPExpression &get_default(); - static const CPPExpression &get_delete(); - - enum ResultType { - RT_integer, - RT_real, - RT_pointer, - RT_error - }; - - class Result { - public: - Result(); - Result(int value); - Result(double value); - Result(void *value); - - int as_integer() const; - double as_real() const; - void *as_pointer() const; - bool as_boolean() const; - void output(std::ostream &out) const; - - ResultType _type; - union { - int _integer; - double _real; - void *_pointer; - } _u; - }; - - - Result evaluate() const; - CPPType *determine_type() const; - bool is_lvalue() const; - bool is_tbd() const; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPExpression *as_expression(); - - Type _type; - std::string _str; - union { - bool _boolean; - unsigned long long _integer; - long double _real; - CPPInstance *_variable; - CPPFunctionGroup *_fgroup; - CPPIdentifier *_ident; - CPPClosureType *_closure_type; - struct { - union { - CPPType *_type; - CPPExpression *_expr; - }; - CPPType *_std_type_info; - } _typeid; - struct { - CPPType *_to; - CPPExpression *_op1; - } _typecast; - struct { - // One of the yytoken values: a character, or something like EQCOMPARE. - int _operator; - CPPExpression *_op1; - CPPExpression *_op2; - CPPExpression *_op3; - } _op; - struct { - CPPInstance *_operator; - CPPExpression *_value; - } _literal; - struct { - int _trait; - CPPType *_type; - CPPType *_arg; - } _type_trait; - } _u; - -protected: - static CPPType *elevate_type(CPPType *t1, CPPType *t2); - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPExpression::Result &result) { - result.output(out); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppExpressionParser.cxx b/dtool/src/cppparser/cppExpressionParser.cxx deleted file mode 100644 index ef5785eb5a..0000000000 --- a/dtool/src/cppparser/cppExpressionParser.cxx +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppExpressionParser.cxx - * @author drose - * @date 1999-10-25 - */ - -#include "cppExpressionParser.h" -#include "cppExpression.h" - -/** - * - */ -CPPExpressionParser:: -CPPExpressionParser(CPPScope *current_scope, CPPScope *global_scope) : - _current_scope(current_scope), - _global_scope(global_scope) -{ - _expr = nullptr; -} - -/** - * - */ -CPPExpressionParser:: -~CPPExpressionParser() { -} - -/** - * - */ -bool CPPExpressionParser:: -parse_expr(const std::string &expr) { - if (!init_const_expr(expr)) { - std::cerr << "Unable to parse expression\n"; - return false; - } - - _expr = parse_const_expr(this, _current_scope, _global_scope); - - return get_error_count() == 0; -} - -/** - * - */ -bool CPPExpressionParser:: -parse_expr(const std::string &expr, const CPPPreprocessor &filepos) { - if (!init_const_expr(expr)) { - std::cerr << "Unable to parse expression\n"; - return false; - } - - copy_filepos(filepos); - - _expr = parse_const_expr(this, _current_scope, _global_scope); - - return get_error_count() == 0; -} - -/** - * - */ -void CPPExpressionParser:: -output(std::ostream &out) const { - if (_expr == nullptr) { - out << "(null expr)"; - } else { - out << *_expr; - } -} diff --git a/dtool/src/cppparser/cppExpressionParser.h b/dtool/src/cppparser/cppExpressionParser.h deleted file mode 100644 index 9a2cdf67a4..0000000000 --- a/dtool/src/cppparser/cppExpressionParser.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppExpressionParser.h - * @author drose - * @date 1999-10-25 - */ - -#ifndef CPPEXPRESSIONPARSER_H -#define CPPEXPRESSIONPARSER_H - -#include "dtoolbase.h" - -#include "cppPreprocessor.h" - -class CPPExpression; -class CPPScope; - -/** - * - */ -class CPPExpressionParser : public CPPPreprocessor { -public: - CPPExpressionParser(CPPScope *current_scope, CPPScope *global_scope); - ~CPPExpressionParser(); - - bool parse_expr(const std::string &expr); - bool parse_expr(const std::string &expr, const CPPPreprocessor &filepos); - - void output(std::ostream &out) const; - - CPPScope *_current_scope; - CPPScope *_global_scope; - CPPExpression *_expr; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPExpressionParser &ep) { - ep.output(out); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppExtensionType.cxx b/dtool/src/cppparser/cppExtensionType.cxx deleted file mode 100644 index f82735274d..0000000000 --- a/dtool/src/cppparser/cppExtensionType.cxx +++ /dev/null @@ -1,281 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppExtensionType.cxx - * @author drose - * @date 1999-10-21 - */ - -#include "cppExtensionType.h" -#include "cppTypedefType.h" -#include "cppIdentifier.h" -#include "cppParser.h" -#include "indent.h" - -/** - * - */ -CPPExtensionType:: -CPPExtensionType(CPPExtensionType::Type type, - CPPIdentifier *ident, CPPScope *current_scope, - const CPPFile &file, CPPAttributeList attr) : - CPPType(file), - _type(type), _ident(ident), - _alignment(nullptr) -{ - if (_ident != nullptr) { - _ident->_native_scope = current_scope; - } - _attributes = std::move(attr); -} - -/** - * - */ -std::string CPPExtensionType:: -get_simple_name() const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_simple_name(); -} - -/** - * - */ -std::string CPPExtensionType:: -get_local_name(CPPScope *scope) const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_local_name(scope); -} - -/** - * - */ -std::string CPPExtensionType:: -get_fully_scoped_name() const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_fully_scoped_name(); -} - -/** - * Returns true if the type has not yet been fully specified, false if it has. - */ -bool CPPExtensionType:: -is_incomplete() const { - return true; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPExtensionType:: -is_tbd() const { - if (_ident != nullptr) { - return _ident->is_tbd(); - } - return false; -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPExtensionType:: -is_standard_layout() const { - return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPExtensionType:: -is_trivial() const { - return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPExtensionType:: -is_trivially_copyable() const { - return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPExtensionType:: -is_constructible(const CPPType *given_type) const { - if (_type == T_enum || _type == T_enum_class || _type == T_enum_struct) { - const CPPExtensionType *other = ((CPPType *)given_type)->remove_reference()->remove_const()->as_extension_type(); - return other != nullptr && is_equal(other); - } - return false; -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPExtensionType:: -is_default_constructible() const { - return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPExtensionType:: -is_copy_constructible() const { - return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPExtensionType:: -is_copy_assignable() const { - return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct); -} - -/** - * - */ -CPPDeclaration *CPPExtensionType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPExtensionType *rep = new CPPExtensionType(*this); - if (_ident != nullptr) { - rep->_ident = - _ident->substitute_decl(subst, current_scope, global_scope); - } - - if (rep->_ident == _ident) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_extension_type(); - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPExtensionType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - if (_ident == nullptr) { - // We can't resolve anonymous types. But that's OK, since they can't be - // forward declared anyway. - return this; - } - - // Maybe it has been defined by now. - CPPType *type = _ident->find_type(current_scope, global_scope); - if (type != nullptr) { - return type; - } - return this; -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPExtensionType:: -is_equivalent(const CPPType &other) const { - const CPPExtensionType *ot = ((CPPType *)&other)->as_extension_type(); - if (ot == nullptr) { - return CPPType::is_equivalent(other); - } - - // We consider two different extension types to be equivalent if they have - // the same name. - - return _ident != nullptr && ot->_ident != nullptr && *_ident == *ot->_ident; -} - -/** - * - */ -void CPPExtensionType:: -output(std::ostream &out, int, CPPScope *scope, bool complete) const { - if (_ident != nullptr) { - // If we have a name, use it. - if (complete || cppparser_output_class_keyword) { - out << _type << " "; - } - if (complete && !_attributes.is_empty()) { - out << _attributes << " "; - } - out << _ident->get_local_name(scope); - - } else if (!_typedefs.empty()) { - // If we have a typedef name, use it. - out << _typedefs.front()->get_local_name(scope); - - } else { - out << "(**unknown forward-reference type**)"; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPExtensionType:: -get_subtype() const { - return ST_extension; -} - -/** - * - */ -CPPExtensionType *CPPExtensionType:: -as_extension_type() { - return this; -} - -std::ostream & -operator << (std::ostream &out, CPPExtensionType::Type type) { - switch (type) { - case CPPExtensionType::T_enum: - return out << "enum"; - - case CPPExtensionType::T_class: - return out << "class"; - - case CPPExtensionType::T_struct: - return out << "struct"; - - case CPPExtensionType::T_union: - return out << "union"; - - case CPPExtensionType::T_enum_class: - return out << "enum class"; - - case CPPExtensionType::T_enum_struct: - return out << "enum struct"; - - default: - return out << "***invalid extension type***"; - } -} diff --git a/dtool/src/cppparser/cppExtensionType.h b/dtool/src/cppparser/cppExtensionType.h deleted file mode 100644 index acdef469b9..0000000000 --- a/dtool/src/cppparser/cppExtensionType.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppExtensionType.h - * @author drose - * @date 1999-10-21 - */ - -#ifndef CPPEXTENSIONTYPE_H -#define CPPEXTENSIONTYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" -#include "cppInstance.h" - -class CPPScope; -class CPPIdentifier; - -/** - * Base class of enum, class, struct, and union types. An instance of the - * base class (instead of one of the specializations) is used for forward - * references. - */ -class CPPExtensionType : public CPPType { -public: - enum Type { - T_enum, - T_class, - T_struct, - T_union, - T_enum_class, - T_enum_struct, - }; - - CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope, - const CPPFile &file, CPPAttributeList attr = CPPAttributeList()); - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual bool is_incomplete() const; - virtual bool is_tbd() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_equivalent(const CPPType &other) const; - - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPExtensionType *as_extension_type(); - - Type _type; - CPPIdentifier *_ident; - CPPExpression *_alignment; -}; - -std::ostream &operator << (std::ostream &out, CPPExtensionType::Type type); - -#endif diff --git a/dtool/src/cppparser/cppFile.cxx b/dtool/src/cppparser/cppFile.cxx deleted file mode 100644 index bc3c5aeed0..0000000000 --- a/dtool/src/cppparser/cppFile.cxx +++ /dev/null @@ -1,144 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppFile.cxx - * @author drose - * @date 1999-11-11 - */ - -#include "cppFile.h" - -#include - -using std::string; - -/** - * - */ -CPPFile:: -CPPFile(const Filename &filename, const Filename &filename_as_referenced, - Source source) : - _filename(filename), _filename_as_referenced(filename_as_referenced), - _source(source), - _pragma_once(false) -{ - _filename.set_text(); - _filename_as_referenced.set_text(); -} - -/** - * Returns true if the file appears to be a C or C++ source code file based on - * its extension. That is, returns true if the filename ends in .c, .C, .cc, - * .cpp, or any of a series of likely extensions. - */ -bool CPPFile:: -is_c_or_i_file() const { - return is_c_or_i_file(_filename); -} - -/** - * Returns true if the file appears to be a C or C++ source code file based on - * its extension. That is, returns true if the filename ends in .c, .C, .cc, - * .cpp, or any of a series of likely extensions. - */ -bool CPPFile:: -is_c_or_i_file(const Filename &filename) { - string extension = filename.get_extension(); - // downcase the extension. - for (string::iterator ei = extension.begin(); - ei != extension.end(); - ++ei) { - (*ei) = tolower(*ei); - } - - return (extension == "c" || extension == "cc" || - extension == "cpp" || extension == "c++" || extension == "cxx" || - extension == "i" || extension == "t"); -} - -/** - * Returns true if the file appears to be a C or C++ source code file based on - * its extension. That is, returns true if the filename ends in .c, .C, .cc, - * .cpp, or any of a series of likely extensions. - */ -bool CPPFile:: -is_c_file() const { - return is_c_file(_filename); -} - -/** - * Returns true if the file appears to be a C or C++ source code file based on - * its extension. That is, returns true if the filename ends in .c, .C, .cc, - * .cpp, or any of a series of likely extensions. - */ -bool CPPFile:: -is_c_file(const Filename &filename) { - string extension = filename.get_extension(); - // downcase the extension. - for (string::iterator ei = extension.begin(); - ei != extension.end(); - ++ei) { - (*ei) = tolower(*ei); - } - - return (extension == "c" || extension == "cc" || - extension == "cpp" || extension == "c++" || extension == "cxx"); -} - -/** - * If the other file is "nearer" than this file (in the sense that a file in - * the local directory is nearer than a file in the system directory, etc.), - * replaces this file's information with that of the other. Otherwise, does - * nothing. - */ -void CPPFile:: -replace_nearer(const CPPFile &other) { - if ((int)_source > (int)other._source) { - (*this) = other; - } -} - -/** - * - */ -bool CPPFile:: -operator < (const CPPFile &other) const { - return _filename < other._filename; -} - -/** - * - */ -bool CPPFile:: -operator == (const CPPFile &other) const { - return _filename == other._filename; -} - -/** - * - */ -bool CPPFile:: -operator != (const CPPFile &other) const { - return _filename != other._filename; -} - -/** - * - */ -const char *CPPFile:: -c_str() const { - return _filename.c_str(); -} - -/** - * - */ -bool CPPFile:: -empty() const { - return _filename.empty(); -} diff --git a/dtool/src/cppparser/cppFile.h b/dtool/src/cppparser/cppFile.h deleted file mode 100644 index 5cc26d5e01..0000000000 --- a/dtool/src/cppparser/cppFile.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppFile.h - * @author drose - * @date 1999-11-11 - */ - -#ifndef CPPFILE_H -#define CPPFILE_H - -#include "dtoolbase.h" -#include "filename.h" - -/** - * This defines a source file (typically a C++ header file) that is parsed by - * the CPPParser. Each declaration indicates the source file where it - * appeared. - */ -class CPPFile { -public: - enum Source { - S_local, // File resides in the current directory - S_alternate, // File resides in some other directory - S_system, // File resides in a system directory - S_none, // File is internally generated - }; - - CPPFile(const Filename &filename = "", - const Filename &filename_as_referenced = "", - Source source = S_none); - - bool is_c_or_i_file() const; - static bool is_c_or_i_file(const Filename &filename); - - bool is_c_file() const; - static bool is_c_file(const Filename &filename); - - void replace_nearer(const CPPFile &other); - - bool operator < (const CPPFile &other) const; - bool operator == (const CPPFile &other) const; - bool operator != (const CPPFile &other) const; - - const char *c_str() const; - bool empty() const; - - Filename _filename; - Filename _filename_as_referenced; - mutable Source _source; - mutable bool _pragma_once; -}; - -inline std::ostream &operator << (std::ostream &out, const CPPFile &file) { - return out << file._filename; -} - -#endif diff --git a/dtool/src/cppparser/cppFunctionGroup.cxx b/dtool/src/cppparser/cppFunctionGroup.cxx deleted file mode 100644 index 7904663d08..0000000000 --- a/dtool/src/cppparser/cppFunctionGroup.cxx +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppFunctionGroup.cxx - * @author drose - * @date 1999-11-11 - */ - -#include "cppFunctionGroup.h" -#include "cppFunctionType.h" -#include "cppInstance.h" -#include "indent.h" - -/** - * - */ -CPPFunctionGroup:: -CPPFunctionGroup(const std::string &name) : - CPPDeclaration(CPPFile()), - _name(name) -{ -} - -/** - * - */ -CPPFunctionGroup:: -~CPPFunctionGroup() { -} - -/** - * If all the functions that share this name have the same return type, - * returns that type. Otherwise, if some functions have different return - * types, returns NULL. - */ -CPPType *CPPFunctionGroup:: -get_return_type() const { - CPPType *return_type = nullptr; - - if (!_instances.empty()) { - Instances::const_iterator ii = _instances.begin(); - return_type = (*ii)->_type->as_function_type()->_return_type; - ++ii; - while (ii != _instances.end()) { - if ((*ii)->_type->as_function_type()->_return_type != return_type) { - return nullptr; - } - ++ii; - } - } - - return return_type; -} - -/** - * - */ -void CPPFunctionGroup:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (!_instances.empty()) { - Instances::const_iterator ii = _instances.begin(); - (*ii)->output(out, indent_level, scope, complete); - ++ii; - while (ii != _instances.end()) { - out << ";\n"; - indent(out, indent_level); - (*ii)->output(out, indent_level, scope, complete); - ++ii; - } - } -} - -/** - * - */ -CPPDeclaration::SubType CPPFunctionGroup:: -get_subtype() const { - return ST_function_group; -} - -/** - * - */ -CPPFunctionGroup *CPPFunctionGroup:: -as_function_group() { - return this; -} diff --git a/dtool/src/cppparser/cppFunctionGroup.h b/dtool/src/cppparser/cppFunctionGroup.h deleted file mode 100644 index 3fced8f4ab..0000000000 --- a/dtool/src/cppparser/cppFunctionGroup.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppFunctionGroup.h - * @author drose - * @date 1999-11-11 - */ - -#ifndef CPPFUNCTIONGROUP_H -#define CPPFUNCTIONGROUP_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -class CPPInstance; - -/** - * This class is simply a container for one or more CPPInstances for functions - * of the same name. It's handy for storing in the CPPScope, so that - * CPPScope::find_symbol() can return a single pointer to indicate all of the - * functions that may share a given name. - */ -class CPPFunctionGroup : public CPPDeclaration { -public: - CPPFunctionGroup(const std::string &name); - ~CPPFunctionGroup(); - - CPPType *get_return_type() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPFunctionGroup *as_function_group(); - - typedef std::vector Instances; - Instances _instances; - std::string _name; -}; - -#endif diff --git a/dtool/src/cppparser/cppFunctionType.cxx b/dtool/src/cppparser/cppFunctionType.cxx deleted file mode 100644 index 9eb7c8fdeb..0000000000 --- a/dtool/src/cppparser/cppFunctionType.cxx +++ /dev/null @@ -1,463 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppFunctionType.cxx - * @author drose - * @date 1999-10-21 - */ - -#include "cppFunctionType.h" -#include "cppParameterList.h" -#include "cppSimpleType.h" -#include "cppInstance.h" - -using std::ostream; -using std::ostringstream; -using std::string; - -/** - * - */ -CPPFunctionType:: -CPPFunctionType(CPPType *return_type, CPPParameterList *parameters, - int flags) : - CPPType(CPPFile()), - _return_type(return_type), - _parameters(parameters), - _flags(flags) -{ - _class_owner = nullptr; - - // If the parameter list contains just the token "void", it means no - // parameters. - if (_parameters != nullptr && - _parameters->_parameters.size() == 1 && - _parameters->_parameters.front()->_type->as_simple_type() != nullptr && - _parameters->_parameters.front()->_type->as_simple_type()->_type == - CPPSimpleType::T_void && - _parameters->_parameters.front()->_ident == nullptr) { - _parameters->_parameters.clear(); - } -} - -/** - * - */ -CPPFunctionType:: -CPPFunctionType(const CPPFunctionType ©) : - CPPType(copy), - _return_type(copy._return_type), - _parameters(copy._parameters), - _flags(copy._flags), - _class_owner(copy._class_owner) -{ -} - -/** - * - */ -void CPPFunctionType:: -operator = (const CPPFunctionType ©) { - CPPType::operator = (copy); - _return_type = copy._return_type; - _parameters = copy._parameters; - _flags = copy._flags; - _class_owner = copy._class_owner; -} - -/** - * Returns true if the function accepts the given number of parameters. - */ -bool CPPFunctionType:: -accepts_num_parameters(int num_parameters) { - assert(num_parameters >= 0); - if (_parameters == nullptr) { - return (num_parameters == 0); - } - - size_t actual_num_parameters = _parameters->_parameters.size(); - // If we passed too many parameters, it must have an ellipsis. - if ((size_t)num_parameters > actual_num_parameters) { - return _parameters->_includes_ellipsis; - } - - // Make sure all superfluous parameters have a default value. - for (size_t i = (size_t)num_parameters; i < actual_num_parameters; ++i) { - CPPInstance *param = _parameters->_parameters[i]; - if (param->_initializer == nullptr) { - return false; - } - } - - return true; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPFunctionType:: -is_fully_specified() const { - return CPPType::is_fully_specified() && - _return_type->is_fully_specified() && - _parameters->is_fully_specified(); -} - -/** - * - */ -CPPDeclaration *CPPFunctionType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPFunctionType *rep = new CPPFunctionType(*this); - if (_return_type != nullptr) { - rep->_return_type = - _return_type->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - } - - if (_parameters != nullptr) { - rep->_parameters = - _parameters->substitute_decl(subst, current_scope, global_scope); - } - - if (rep->_return_type == _return_type && - rep->_parameters == _parameters) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_function_type(); - - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPFunctionType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *rtype = _return_type->resolve_type(current_scope, global_scope); - CPPParameterList *params; - if (_parameters == nullptr) { - params = nullptr; - } else { - params = _parameters->resolve_type(current_scope, global_scope); - } - - if (rtype != _return_type || params != _parameters) { - CPPFunctionType *rep = new CPPFunctionType(*this); - rep->_return_type = rtype; - rep->_parameters = params; - return CPPType::new_type(rep); - } - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPFunctionType:: -is_tbd() const { - if (_return_type->is_tbd()) { - return true; - } - return _parameters == nullptr || _parameters->is_tbd(); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPFunctionType:: -is_trivial() const { - return false; -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPFunctionType:: -is_trivially_copyable() const { - return false; -} - -/** - * - */ -void CPPFunctionType:: -output(ostream &out, int indent_level, CPPScope *scope, bool complete) const { - output(out, indent_level, scope, complete, -1); -} - -/** - * The additional parameter allows us to specify the number of parameters we - * wish to show the default values for. If num_default_parameters is >= 0, it - * indicates the number of default parameter values to show on output. - * Otherwise, all parameter values are shown. - */ -void CPPFunctionType:: -output(ostream &out, int indent_level, CPPScope *scope, bool complete, - int num_default_parameters) const { - - if (_flags & F_trailing_return_type) { - // It was declared using trailing return type, so let's format it that - // way. - out << "auto("; - _parameters->output(out, scope, true, num_default_parameters); - out << ")"; - if (_flags & F_const_method) { - out << " const"; - } - if (_flags & F_noexcept) { - out << " noexcept"; - } - if (_flags & F_final) { - out << " final"; - } - if (_flags & F_override) { - out << " override"; - } - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - out << " -> "; - _return_type->output(out, indent_level, scope, false); - } - else { - _return_type->output(out, indent_level, scope, complete); - out << "("; - _parameters->output(out, scope, true, num_default_parameters); - out << ")"; - if (_flags & F_const_method) { - out << " const"; - } - if (_flags & F_noexcept) { - out << " noexcept"; - } - if (_flags & F_final) { - out << " final"; - } - if (_flags & F_override) { - out << " override"; - } - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - } -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPFunctionType:: -output_instance(ostream &out, int indent_level, CPPScope *scope, - bool complete, const string &prename, - const string &name) const { - output_instance(out, indent_level, scope, complete, prename, name, -1); -} - -/** - * The additional parameter allows us to specify the number of parameters we - * wish to show the default values for. If num_default_parameters is >= 0, it - * indicates the number of default parameter values to show on output. - * Otherwise, all parameter values are shown. - */ -void CPPFunctionType:: -output_instance(ostream &out, int indent_level, CPPScope *scope, - bool complete, const string &prename, - const string &name, int num_default_parameters) const { - ostringstream parm_string; - parm_string << "("; - _parameters->output(parm_string, scope, true, num_default_parameters); - parm_string << ")"; - string str = parm_string.str(); - - if (_flags & (F_constructor | F_destructor)) { - // No return type for constructors and destructors. - out << prename << name << str; - } - else if (_flags & F_trailing_return_type) { - // It was declared using trailing return type, so let's format it that - // way. - out << "auto "; - - if (prename.empty()) { - out << name; - } else { - out << "(" << prename << name << ")"; - } - - out << str; - } - else if (_flags & F_operator_typecast) { - out << "operator "; - _return_type->output_instance(out, indent_level, scope, complete, - "", prename + str); - } - else { - if (prename.empty()) { - _return_type->output_instance(out, indent_level, scope, complete, - "", prename + name + str); - } else { - _return_type->output_instance(out, indent_level, scope, complete, - "", "(" + prename + name + ")" + str); - } - } - - if (_flags & F_const_method) { - out << " const"; - } - if (_flags & F_volatile_method) { - out << " volatile"; - } - if (_flags & F_noexcept) { - out << " noexcept"; - } - if (_flags & F_final) { - out << " final"; - } - if (_flags & F_override) { - out << " override"; - } - - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - - if (_flags & F_trailing_return_type) { - out << " -> "; - _return_type->output(out, indent_level, scope, false); - } -} - -/** - * Returns the number of parameters in the list that may take default values. - */ -int CPPFunctionType:: -get_num_default_parameters() const { - // The trick is just to count, beginning from the end and working towards - // the front, the number of parameters that have some initializer. - - if (_parameters == nullptr) { - return 0; - } - - const CPPParameterList::Parameters ¶ms = _parameters->_parameters; - CPPParameterList::Parameters::const_reverse_iterator pi; - int count = 0; - for (pi = params.rbegin(); - pi != params.rend() && (*pi)->_initializer != nullptr; - ++pi) { - count++; - } - - return count; -} - -/** - * - */ -CPPDeclaration::SubType CPPFunctionType:: -get_subtype() const { - return ST_function; -} - -/** - * - */ -CPPFunctionType *CPPFunctionType:: -as_function_type() { - return this; -} - -/** - * This is similar to is_equal(), except it is more forgiving: it considers - * the functions to be equivalent only if the return type and the types of all - * parameters match. - * - * Note that this isn't symmetric to account for covariant return types. - */ -bool CPPFunctionType:: -match_virtual_override(const CPPFunctionType &other) const { - if (!_return_type->is_equivalent(*other._return_type) && - !_return_type->is_convertible_to(other._return_type)) { - return false; - } - - if (((_flags ^ other._flags) & ~(F_override | F_final)) != 0) { - return false; - } - - if (!_parameters->is_equivalent(*other._parameters)) { - return false; - } - - return true; -} - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPFunctionType:: -is_equal(const CPPDeclaration *other) const { - const CPPFunctionType *ot = ((CPPDeclaration *)other)->as_function_type(); - assert(ot != nullptr); - - if (_return_type != ot->_return_type) { - return false; - } - if (_flags != ot->_flags) { - return false; - } - if (_parameters == ot->_parameters) { - return true; - } - if (_parameters == nullptr || ot->_parameters == nullptr || - *_parameters != *ot->_parameters) { - return false; - } - return true; -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPFunctionType:: -is_less(const CPPDeclaration *other) const { - const CPPFunctionType *ot = ((CPPDeclaration *)other)->as_function_type(); - assert(ot != nullptr); - - if (_return_type != ot->_return_type) { - return _return_type < ot->_return_type; - } - if (_flags != ot->_flags) { - return _flags < ot->_flags; - } - if (_parameters == ot->_parameters) { - return 0; - } - if (_parameters == nullptr || ot->_parameters == nullptr) { - return _parameters < ot->_parameters; - } - return *_parameters < *ot->_parameters; -} diff --git a/dtool/src/cppparser/cppFunctionType.h b/dtool/src/cppparser/cppFunctionType.h deleted file mode 100644 index 3370a079a4..0000000000 --- a/dtool/src/cppparser/cppFunctionType.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppFunctionType.h - * @author drose - * @date 1999-10-21 - */ - -#ifndef CPPFUNCTIONTYPE_H -#define CPPFUNCTIONTYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -class CPPParameterList; -class CPPIdentifier; - -/** - * - */ -class CPPFunctionType : public CPPType { -public: - enum Flags { - F_const_method = 0x001, - F_operator_typecast = 0x002, - F_constructor = 0x004, - F_destructor = 0x008, - F_method_pointer = 0x010, - F_unary_op = 0x020, - F_operator = 0x040, - F_noexcept = 0x080, - F_copy_constructor = 0x200, - F_move_constructor = 0x400, - F_trailing_return_type = 0x800, - F_final = 0x1000, - F_override = 0x2000, - F_volatile_method = 0x4000, - F_lvalue_method = 0x8000, - F_rvalue_method = 0x10000, - F_copy_assignment_operator = 0x20000, - F_move_assignment_operator = 0x40000, - }; - - CPPFunctionType(CPPType *return_type, CPPParameterList *parameters, - int flags); - CPPFunctionType(const CPPFunctionType ©); - void operator = (const CPPFunctionType ©); - - bool accepts_num_parameters(int num_parameters); - - CPPType *_return_type; - CPPParameterList *_parameters; - int _flags; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, int num_default_parameters) const; - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name, - int num_default_parameters) const; - int get_num_default_parameters() const; - - virtual SubType get_subtype() const; - - virtual CPPFunctionType *as_function_type(); - - bool match_virtual_override(const CPPFunctionType &other) const; - - CPPIdentifier *_class_owner; - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppGlobals.cxx b/dtool/src/cppparser/cppGlobals.cxx deleted file mode 100644 index f537ce8c42..0000000000 --- a/dtool/src/cppparser/cppGlobals.cxx +++ /dev/null @@ -1,16 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppGlobals.cxx - * @author drose - * @date 2000-05-16 - */ - -#include "cppGlobals.h" - -std::string cpp_longlong_keyword; diff --git a/dtool/src/cppparser/cppGlobals.h b/dtool/src/cppparser/cppGlobals.h deleted file mode 100644 index 39755f18d7..0000000000 --- a/dtool/src/cppparser/cppGlobals.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppGlobals.h - * @author drose - * @date 2000-05-16 - */ - -#ifndef CPPGLOBALS_H -#define CPPGLOBALS_H - -#include "dtoolbase.h" - -// Some compilers (notably VC++) define a special keyword to represent a -// 64-bit integer, but don't recognize "long long int". To parse (and -// generate) code for these compilers, set this string to the 64-bit integer -// typename keyword. -extern std::string cpp_longlong_keyword; - - -#endif diff --git a/dtool/src/cppparser/cppIdentifier.cxx b/dtool/src/cppparser/cppIdentifier.cxx deleted file mode 100644 index 5c7a8d72ab..0000000000 --- a/dtool/src/cppparser/cppIdentifier.cxx +++ /dev/null @@ -1,612 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppIdentifier.cxx - * @author drose - * @date 1999-10-26 - */ - -#include "cppIdentifier.h" -#include "cppScope.h" -#include "cppTemplateScope.h" -#include "cppPreprocessor.h" -#include "cppTemplateParameterList.h" -#include "cppTBDType.h" -#include "cppStructType.h" - -using std::string; - - -/** - * - */ -CPPIdentifier:: -CPPIdentifier(const string &name, const CPPFile &file) { - _names.push_back(CPPNameComponent(name)); - _native_scope = nullptr; - _loc.first_line = 0; - _loc.first_column = 0; - _loc.last_line = 0; - _loc.last_column = 0; - _loc.file = file; -} - -/** - * - */ -CPPIdentifier:: -CPPIdentifier(const CPPNameComponent &name, const CPPFile &file) { - _names.push_back(name); - _native_scope = nullptr; - _loc.first_line = 0; - _loc.first_column = 0; - _loc.last_line = 0; - _loc.last_column = 0; - _loc.file = file; -} - -/** - * - */ -CPPIdentifier:: -CPPIdentifier(const string &name, const cppyyltype &loc) : _loc(loc) { - _names.push_back(CPPNameComponent(name)); - _native_scope = nullptr; -} - -/** - * - */ -CPPIdentifier:: -CPPIdentifier(const CPPNameComponent &name, const cppyyltype &loc) : _loc(loc) { - _names.push_back(name); - _native_scope = nullptr; -} - -/** - * - */ -void CPPIdentifier:: -add_name(const string &name) { - _names.push_back(CPPNameComponent(name)); -} - -/** - * - */ -void CPPIdentifier:: -add_name(const CPPNameComponent &name) { - _names.push_back(name); -} - -/** - * - */ -void CPPIdentifier:: -prepend(CPPIdentifier *ident) { - _names.insert(_names.begin(), ident->_names.begin(), ident->_names.end()); -} - -/** - * - */ -bool CPPIdentifier:: -operator == (const CPPIdentifier &other) const { - if (_names.size() != other._names.size()) { - return false; - } - for (int i = 0; i < (int)_names.size(); ++i) { - if (_names[i] != other._names[i]) { - return false; - } - } - - return true; -} - -/** - * - */ -bool CPPIdentifier:: -operator != (const CPPIdentifier &other) const { - return !(*this == other); -} - -/** - * - */ -bool CPPIdentifier:: -operator < (const CPPIdentifier &other) const { - if (_names.size() != other._names.size()) { - return _names.size() < other._names.size(); - } - for (int i = 0; i < (int)_names.size(); ++i) { - if (_names[i] != other._names[i]) { - return _names[i] < other._names[i]; - } - } - - return false; -} - -/** - * - */ -bool CPPIdentifier:: -is_scoped() const { - return _names.size() > 1; -} - - -/** - * - */ -string CPPIdentifier:: -get_simple_name() const { - return _names.back().get_name(); -} - -/** - * - */ -string CPPIdentifier:: -get_local_name(CPPScope *scope) const { - assert(!_names.empty()); - - string result; - - if (scope == nullptr || (_native_scope == nullptr && _names.size() == 1)) { - result = _names.back().get_name_with_templ(scope); - - } else if (_names.front().empty()) { - result = get_fully_scoped_name(); - - } else { - // Determine the scope of everything up until but not including the last - // name. - CPPScope *my_scope = get_scope(scope, nullptr); - - // Strip off template scopes, since they don't add anything particularly - // meaningful to the local name. - while (my_scope != nullptr && my_scope->as_template_scope() != nullptr) { - my_scope = my_scope->get_parent_scope(); - } - - if (my_scope == nullptr) { - result = get_fully_scoped_name(); - } else if (my_scope == scope) { - return _names.back().get_name_with_templ(scope); - } else { - result = my_scope->get_local_name(scope); - if (!result.empty()) { - result += "::"; - } - result += _names.back().get_name_with_templ(scope); - } - } - return result; -} - -/** - * - */ -string CPPIdentifier:: -get_fully_scoped_name() const { - assert(!_names.empty()); - Names::const_iterator ni = _names.begin(); - string name = (*ni).get_name_with_templ(); - ++ni; - while (ni != _names.end()) { - name += "::" + (*ni).get_name_with_templ(); - ++ni; - } - return name; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPIdentifier:: -is_fully_specified() const { - Names::const_iterator ni; - for (ni = _names.begin(); ni != _names.end(); ++ni) { - if ((*ni).has_templ() && !(*ni).get_templ()->is_fully_specified()) { - return false; - } - } - - return true; -} - -/** - * Returns true if the identifier includes a template parameter list that - * includes some not-yet-defined type. - */ -bool CPPIdentifier:: -is_tbd() const { - Names::const_iterator ni; - for (ni = _names.begin(); ni != _names.end(); ++ni) { - if ((*ni).is_tbd()) { - return true; - } - } - - return false; -} - -/** - * - */ -CPPScope *CPPIdentifier:: -get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - assert(!_names.empty()); - - CPPScope *scope = _native_scope; - if (scope == nullptr) { - scope = current_scope; - } - int i = 0; - - if (_names[i].empty()) { - // This identifier starts with a ::, thus it begins at the global scope. - scope = global_scope; - i++; - } - - while (i + 1 < (int)_names.size() && scope != nullptr) { - // Check for an explicitly specialized scope first. - CPPScope *next_scope = scope->find_scope(_names[i].get_name_with_templ(), global_scope); - if (next_scope == nullptr) { - next_scope = scope->find_scope(_names[i].get_name(), global_scope); - if (next_scope == nullptr) { - if (error_sink != nullptr) { - error_sink->error("Symbol " + _names[i].get_name() + - " is not a known scope in " + - scope->get_fully_scoped_name(), - _loc); - } - return nullptr; - } - if (_names[i].has_templ()) { - next_scope = next_scope->instantiate(_names[i].get_templ(), - current_scope, global_scope); - } - } - scope = next_scope; - i++; - } - - return scope; -} - -/** - * - */ -CPPScope *CPPIdentifier:: -get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPDeclaration::SubstDecl &subst, - CPPPreprocessor *error_sink) const { - assert(!_names.empty()); - - CPPScope *scope = _native_scope; - if (scope == nullptr) { - scope = current_scope; - } - int i = 0; - - if (_names[i].empty()) { - // This identifier starts with a ::, thus it begins at the global scope. - scope = global_scope; - i++; - } - - while (i + 1 < (int)_names.size() && scope != nullptr) { - CPPScope *next_scope = scope->find_scope(_names[i].get_name(), subst, - global_scope); - if (next_scope == nullptr) { - if (error_sink != nullptr) { - error_sink->error("Symbol " + _names[i].get_name() + - " is not a known scope in " + - scope->get_fully_scoped_name(), - _loc); - } - return nullptr; - } - if (_names[i].has_templ()) { - next_scope = next_scope->instantiate(_names[i].get_templ(), - current_scope, global_scope); - } - scope = next_scope; - i++; - } - - return scope; -} - -/** - * Looks up the identifier in the current and/or global scopes, and returns a - * CPPType pointer if it seems to refer to a type, or NULL if it does not. If - * force_instantiate is true, the type will be instantiated as fully as - * possible right now, even if it means instantiating it into an identical - * template type. Otherwise, the instantiation may be delayed for - * optimization reasons, and a CPPTBDType placeholder may be returned instead. - */ -CPPType *CPPIdentifier:: -find_type(CPPScope *current_scope, CPPScope *global_scope, - bool force_instantiate, - CPPPreprocessor *error_sink) const { - CPPScope *scope = get_scope(current_scope, global_scope, error_sink); - if (scope == nullptr) { - return nullptr; - } - - CPPType *type = nullptr; - if (!_names.back().has_templ()) { - type = scope->find_type(get_simple_name()); - - } else { - CPPDeclaration *decl = find_symbol(current_scope, global_scope, error_sink); - type = decl->as_type(); - /* - if (type != NULL) { - if (!type->is_incomplete() || force_instantiate) { - type = type->instantiate(_names.back().get_templ(), - current_scope, global_scope, - error_sink)->as_type(); - - // If we ended up with another template, instantiate later. - if (type->is_template() && !force_instantiate) { - type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this)); - } - - } else { - // Otherwise, we'll have to instantiate the type later. - type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this)); - } - // type->_file.replace_nearer(_file); - } - */ - } - return type; -} - -/** - * This flavor of find_type() will instantiate any scope names in the - * identifier. It's useful for fully defining a type while instantiating a - * class. - */ -CPPType *CPPIdentifier:: -find_type(CPPScope *current_scope, CPPScope *global_scope, - CPPDeclaration::SubstDecl &subst, - CPPPreprocessor *error_sink) const { - CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink); - if (scope == nullptr) { - return nullptr; - } - - CPPType *type = scope->find_type(get_simple_name(), subst, global_scope); - if (type != nullptr && _names.back().has_templ()) { - // This is a template type. - - if (is_fully_specified()) { - // If our identifier fully specifies the instantiation, then apply it. - CPPDeclaration *decl = - type->instantiate(_names.back().get_templ(), - current_scope, global_scope, - error_sink); - assert(decl != nullptr); - CPPType *new_type = decl->as_type(); - assert(new_type != nullptr); - if (new_type == type) { - type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this)); - } else { - type = new_type; - } - } else { - // Otherwise, we'll have to instantiate the type later. - type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this)); - } - // type->_file.replace_nearer(_file); - } - return type; -} - - -/** - * - */ -CPPDeclaration *CPPIdentifier:: -find_symbol(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - CPPScope *scope = get_scope(current_scope, global_scope, error_sink); - if (scope == nullptr) { - return nullptr; - } - - CPPDeclaration *sym; - if (!_names.back().has_templ()) { - if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) { -/** - - */ - sym = scope->get_struct_type()->get_constructor(); - } else { - sym = scope->find_symbol(get_simple_name()); - } - - } else { - sym = scope->find_template(get_simple_name()); - if (sym != nullptr) { - CPPType *type = sym->as_type(); - if (type != nullptr && type->is_incomplete()) { - // We can't instantiate an incomplete type. - sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this)); - } else { - // Instantiate the symbol. - sym = sym->instantiate(_names.back().get_templ(), current_scope, - global_scope, error_sink); - } - } - } - - return sym; -} - -/** - * - */ -CPPDeclaration *CPPIdentifier:: -find_symbol(CPPScope *current_scope, CPPScope *global_scope, - CPPDeclaration::SubstDecl &subst, - CPPPreprocessor *error_sink) const { - CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink); - if (scope == nullptr) { - return nullptr; - } - - CPPDeclaration *sym; - if (!_names.back().has_templ()) { - if (_names.size() > 1 && scope->get_simple_name() == get_simple_name()) { -/** - - */ - sym = scope->get_struct_type()->get_constructor(); - } else { - sym = scope->find_symbol(get_simple_name()); - } - - } else { - sym = scope->find_template(get_simple_name()); - - if (sym != nullptr) { - CPPType *type = sym->as_type(); - if (type != nullptr && type->is_incomplete()) { - // We can't instantiate an incomplete type. - sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this)); - } else { - // Instantiate the symbol. - sym = sym->instantiate(_names.back().get_templ(), current_scope, - global_scope, error_sink); - } - } - } - - return sym; -} - -/** - * - */ -CPPDeclaration *CPPIdentifier:: -find_template(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - CPPScope *scope = get_scope(current_scope, global_scope, error_sink); - if (scope == nullptr) { - return nullptr; - } - return scope->find_template(get_simple_name()); -} - -/** - * - */ -CPPScope *CPPIdentifier:: -find_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - CPPScope *scope = get_scope(current_scope, global_scope, error_sink); - if (scope == nullptr) { - return nullptr; - } - return scope->find_scope(get_simple_name(), global_scope); -} - - -/** - * - */ -CPPIdentifier *CPPIdentifier:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPIdentifier *rep = new CPPIdentifier(*this); - - bool anything_changed = false; - for (int i = 0; i < (int)rep->_names.size(); ++i) { - if (_names[i].has_templ()) { - rep->_names[i].set_templ - (_names[i].get_templ()->substitute_decl(subst, current_scope, global_scope)); - if (rep->_names[i].get_templ() != _names[i].get_templ()) { - anything_changed = true; - } - } - } - - if (!anything_changed) { - delete rep; - rep = this; - } - - return rep; -} - -/** - * - */ -void CPPIdentifier:: -output(std::ostream &out, CPPScope *scope) const { - if (scope == nullptr) { - output_fully_scoped_name(out); - } else { - output_local_name(out, scope); - } -} - - -/** - * - */ -void CPPIdentifier:: -output_local_name(std::ostream &out, CPPScope *scope) const { - assert(!_names.empty()); - - if (scope == nullptr || (_native_scope == nullptr && _names.size() == 1)) { - out << _names.back(); - } else if (_names.front().empty()) { - output_fully_scoped_name(out); - } else { - // Determine the scope of everything up until but not including the last - // name. - CPPScope *my_scope = get_scope(scope, nullptr); - - if (my_scope == nullptr) { - output_fully_scoped_name(out); - } else { - out << my_scope->get_local_name(scope) << "::" << _names.back(); - } - } -} - -/** - * - */ -void CPPIdentifier:: -output_fully_scoped_name(std::ostream &out) const { - if (_native_scope != nullptr) { - _native_scope->output(out, nullptr); - out << "::"; - } - Names::const_iterator ni = _names.begin(); - out << (*ni); - ++ni; - while (ni != _names.end()) { - out << "::" << (*ni); - ++ni; - } -} diff --git a/dtool/src/cppparser/cppIdentifier.h b/dtool/src/cppparser/cppIdentifier.h deleted file mode 100644 index bd6d3df862..0000000000 --- a/dtool/src/cppparser/cppIdentifier.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppIdentifier.h - * @author drose - * @date 1999-10-26 - */ - -#ifndef CPPIDENTIFIER_H -#define CPPIDENTIFIER_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" -#include "cppNameComponent.h" -#include "cppFile.h" -#include "cppBisonDefs.h" - -#include -#include - -class CPPScope; -class CPPType; -class CPPPreprocessor; -class CPPTemplateParameterList; - -/** - * - */ -class CPPIdentifier { -public: - CPPIdentifier(const std::string &name, const CPPFile &file = CPPFile()); - CPPIdentifier(const CPPNameComponent &name, const CPPFile &file = CPPFile()); - CPPIdentifier(const std::string &name, const cppyyltype &loc); - CPPIdentifier(const CPPNameComponent &name, const cppyyltype &loc); - void add_name(const std::string &name); - void add_name(const CPPNameComponent &name); - - void prepend(CPPIdentifier *ident); - - bool operator == (const CPPIdentifier &other) const; - bool operator != (const CPPIdentifier &other) const; - bool operator < (const CPPIdentifier &other) const; - - bool is_scoped() const; - - std::string get_simple_name() const; - std::string get_local_name(CPPScope *scope = nullptr) const; - std::string get_fully_scoped_name() const; - - bool is_fully_specified() const; - bool is_tbd() const; - - - CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPDeclaration::SubstDecl &subst, - CPPPreprocessor *error_sink = nullptr) const; - - CPPType *find_type(CPPScope *current_scope, CPPScope *global_scope, - bool force_instantiate = false, - CPPPreprocessor *error_sink = nullptr) const; - CPPType *find_type(CPPScope *current_scope, CPPScope *global_scope, - CPPDeclaration::SubstDecl &subst, - CPPPreprocessor *error_sink = nullptr) const; - CPPDeclaration *find_symbol(CPPScope *current_scope, - CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - CPPDeclaration *find_symbol(CPPScope *current_scope, - CPPScope *global_scope, - CPPDeclaration::SubstDecl &subst, - CPPPreprocessor *error_sink = nullptr) const; - CPPDeclaration *find_template(CPPScope *current_scope, - CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - CPPScope *find_scope(CPPScope *current_scope, - CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - CPPIdentifier *substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - void output(std::ostream &out, CPPScope *scope) const; - void output_local_name(std::ostream &out, CPPScope *scope) const; - void output_fully_scoped_name(std::ostream &out) const; - - typedef std::vector Names; - Names _names; - CPPScope *_native_scope; - cppyyltype _loc; -}; - -inline std::ostream &operator << (std::ostream &out, const CPPIdentifier &identifier) { - identifier.output(out, nullptr); - return out; -} - - -#endif diff --git a/dtool/src/cppparser/cppInstance.cxx b/dtool/src/cppparser/cppInstance.cxx deleted file mode 100644 index 7de5798729..0000000000 --- a/dtool/src/cppparser/cppInstance.cxx +++ /dev/null @@ -1,637 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppInstance.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppInstance.h" -#include "cppInstanceIdentifier.h" -#include "cppIdentifier.h" -#include "cppTemplateScope.h" -#include "cppFunctionType.h" -#include "cppSimpleType.h" -#include "cppExpression.h" -#include "cppPreprocessor.h" -#include "cppParameterList.h" -#include "cppReferenceType.h" -#include "cppConstType.h" -#include "indent.h" - -#include - -using std::string; - -/** - * - */ -CPPInstance:: -CPPInstance(CPPType *type, const string &name, int storage_class) : - CPPDeclaration(CPPFile()), - _type(type), - _ident(new CPPIdentifier(name)), - _storage_class(storage_class), - _bit_width(-1) -{ - _initializer = nullptr; -} - -/** - * - */ -CPPInstance:: -CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) : - CPPDeclaration(CPPFile()), - _type(type), - _ident(ident), - _storage_class(storage_class), - _bit_width(-1) -{ - _initializer = nullptr; -} - -/** - * Constructs a new CPPInstance object that defines a variable of the - * indicated type according to the type and the InstanceIdentifier. The - * InstanceIdentifier pointer is deallocated. - */ -CPPInstance:: -CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class, - const CPPFile &file) : - CPPDeclaration(file) -{ - _type = ii->unroll_type(type); - _ident = ii->_ident; - _attributes = ii->_attributes; - ii->_ident = nullptr; - _storage_class = storage_class; - _initializer = nullptr; - - if (ii->_bit_width != nullptr) { - CPPExpression::Result result = ii->_bit_width->evaluate(); - if (result._type != CPPExpression::RT_error) { - _bit_width = ii->_bit_width->evaluate().as_integer(); - } else { - _bit_width = -1; - } - } else { - _bit_width = -1; - } - - CPPParameterList *params = ii->get_initializer(); - if (params != nullptr) { - // In this case, the instance has a parameter-list initializer, e.g.: int - // foo(0); We really should save this initializer in the instance object. - // But we don't for now, since no one really cares about initializers - // anyway. - } - - if (ii->_packed) { - _storage_class |= SC_parameter_pack; - } - - delete ii; -} - -/** - * - */ -CPPInstance:: -CPPInstance(const CPPInstance ©) : - CPPDeclaration(copy), - _type(copy._type), - _ident(copy._ident), - _initializer(copy._initializer), - _storage_class(copy._storage_class), - _bit_width(copy._bit_width) -{ - assert(_type != nullptr); -} - -/** - * - */ -CPPInstance:: -~CPPInstance() { - // Can't delete the identifier. Don't try. -} - - -/** - * Constructs and returns a new CPPInstance object that corresponds to a - * function prototype declaration for a typecast method, whose return type is - * implicit in the identifier type. - */ -CPPInstance *CPPInstance:: -make_typecast_function(CPPInstance *inst, CPPIdentifier *ident, - CPPParameterList *parameters, int function_flags) { - CPPType *type = CPPType::new_type(inst->_type); - delete inst; - - function_flags |= (int)CPPFunctionType::F_operator_typecast; - - CPPType *ft = - CPPType::new_type(new CPPFunctionType(type, parameters, function_flags)); - - return new CPPInstance(ft, ident); -} - -/** - * - */ -bool CPPInstance:: -operator == (const CPPInstance &other) const { - if (_type != other._type) { - return false; - } - if (_storage_class != other._storage_class) { - return false; - } - if (_attributes != other._attributes) { - return false; - } - - // We *do* care about the identifier. We need to differentiate types of - // function variables, among possibly other things, based on the identifier. - if ((_ident == nullptr && other._ident != nullptr) || - (_ident != nullptr && other._ident == nullptr) || - (_ident != nullptr && other._ident != nullptr && *_ident != *other._ident)) - { - return false; - } - - // We similarly care about the initializer. - if ((_initializer == nullptr && other._initializer != nullptr) || - (_initializer != nullptr && other._initializer == nullptr) || - (_initializer != nullptr && other._initializer != nullptr && - *_initializer != *other._initializer)) - { - return false; - } - - return true; -} - -/** - * - */ -bool CPPInstance:: -operator != (const CPPInstance &other) const { - return !operator == (other); -} - -/** - * - */ -bool CPPInstance:: -operator < (const CPPInstance &other) const { - if (_type != other._type) { - return _type < other._type; - } - if (_storage_class != other._storage_class) { - return _storage_class < other._storage_class; - } - if (_attributes != other._attributes) { - return _attributes < other._attributes; - } - - // We *do* care about the identifier. We need to differentiate types of - // function variables, among possibly other things, based on the identifier. - if ((_ident == nullptr && other._ident != nullptr) || - (_ident != nullptr && other._ident == nullptr) || - (_ident != nullptr && other._ident != nullptr && *_ident != *other._ident)) - { - if (_ident == nullptr || other._ident == nullptr) { - return _ident < other._ident; - } - return *_ident < *other._ident; - } - - // We similarly care about the initializer. - if ((_initializer == nullptr && other._initializer != nullptr) || - (_initializer != nullptr && other._initializer == nullptr) || - (_initializer != nullptr && other._initializer != nullptr && - *_initializer != *other._initializer)) - { - if (_initializer == nullptr || other._initializer == nullptr) { - return _initializer < other._initializer; - } - return *_initializer < *other._initializer; - } - - return false; -} - -/** - * Sets the value of the expression that is used to initialize the variable, - * or the default value for a parameter. If a non-null expression is set on a - * function declaration, it implies that the function is pure virtual. - */ -void CPPInstance:: -set_initializer(CPPExpression *initializer) { - if (_type->as_function_type() != nullptr) { - // This is a function declaration. - _storage_class &= ~(SC_pure_virtual | SC_defaulted | SC_deleted); - _initializer = nullptr; - - if (initializer != nullptr) { - if (initializer->_type == CPPExpression::T_integer) { // = 0 - _storage_class |= SC_pure_virtual; - - } else if (initializer->_type == CPPExpression::T_default) { - _storage_class |= SC_defaulted; - - } else if (initializer->_type == CPPExpression::T_delete) { - _storage_class |= SC_deleted; - } - } - } else { - _initializer = initializer; - } -} - -/** - * Sets the number of bytes to align this instance to. - */ -void CPPInstance:: -set_alignment(int align) { - _attributes.add_alignas(align); -} - -/** - * Sets the expression that is used to determine the required alignment for - * the variable. This should be a constant expression, but we don't presently - * verify that it is. - */ -void CPPInstance:: -set_alignment(CPPExpression *const_expr) { - _attributes.add_alignas(const_expr); -} - -/** - * - */ -bool CPPInstance:: -is_scoped() const { - if (_ident == nullptr) { - return false; - } else { - return _ident->is_scoped(); - } -} - -/** - * - */ -CPPScope *CPPInstance:: -get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - if (_ident == nullptr) { - return current_scope; - } else { - return _ident->get_scope(current_scope, global_scope, error_sink); - } -} - -/** - * - */ -string CPPInstance:: -get_simple_name() const { - if (_ident == nullptr) { - return ""; - } else { - return _ident->get_simple_name(); - } -} - -/** - * - */ -string CPPInstance:: -get_local_name(CPPScope *scope) const { - if (_ident == nullptr) { - return ""; - } else { - return _ident->get_local_name(scope); - } -} - -/** - * - */ -string CPPInstance:: -get_fully_scoped_name() const { - if (_ident == nullptr) { - return ""; - } else { - return _ident->get_fully_scoped_name(); - } -} - -/** - * If this is a function type instance, checks whether the function name - * matches the class name (or ~name), and if so, flags it as a constructor, - * destructor or assignment operator - */ -void CPPInstance:: -check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) { - CPPScope *scope = get_scope(current_scope, global_scope); - if (scope == nullptr) { - scope = current_scope; - } - - CPPFunctionType *func = _type->as_function_type(); - if (func != nullptr && scope != nullptr) { - string method_name = get_local_name(scope); - string class_name = scope->get_local_name(); - - if (!method_name.empty() && !class_name.empty()) { - // Check either a constructor or assignment operator. - if (method_name == class_name || method_name == "operator =") { - CPPType *void_type = CPPType::new_type - (new CPPSimpleType(CPPSimpleType::T_void)); - - int flags = func->_flags; - if (method_name == class_name) { - flags |= CPPFunctionType::F_constructor; - } - - CPPParameterList *params = func->_parameters; - if (params->_parameters.size() == 1 && !params->_includes_ellipsis) { - CPPType *param_type = params->_parameters[0]->_type; - CPPReferenceType *ref_type = param_type->as_reference_type(); - - if (ref_type != nullptr) { - param_type = ref_type->_pointing_at->remove_cv(); - - if (class_name == param_type->get_simple_name()) { - if (flags & CPPFunctionType::F_constructor) { - if (ref_type->_value_category == CPPReferenceType::VC_rvalue) { - flags |= CPPFunctionType::F_move_constructor; - } else { - flags |= CPPFunctionType::F_copy_constructor; - } - } else { - if (ref_type->_value_category == CPPReferenceType::VC_rvalue) { - flags |= CPPFunctionType::F_move_assignment_operator; - } else { - flags |= CPPFunctionType::F_copy_assignment_operator; - } - } - } - } - } - - _type = CPPType::new_type - (new CPPFunctionType(void_type, func->_parameters, flags)); - - } else if (method_name == "~" + class_name) { - CPPType *void_type = CPPType::new_type - (new CPPSimpleType(CPPSimpleType::T_void)); - - _type = CPPType::new_type - (new CPPFunctionType(void_type, func->_parameters, - func->_flags | CPPFunctionType::F_destructor)); - } - } - } -} - -/** - * - */ -CPPDeclaration *CPPInstance:: -instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - - if (!is_template()) { - if (error_sink != nullptr) { - error_sink->warning("Ignoring template parameters for instance " + - _ident->get_local_name()); - } - return (CPPInstance *)this; - } - - Instantiations::const_iterator ii; - ii = _instantiations.find(actual_params); - if (ii != _instantiations.end()) { - // We've already instantiated this instance with these parameters. Return - // that. - return (*ii).second; - } - - - CPPTemplateScope *tscope = get_template_scope(); - - CPPDeclaration::SubstDecl subst; - actual_params->build_subst_decl(tscope->_parameters, subst, - current_scope, global_scope); - - CPPInstance *inst = - ((CPPInstance *)this)->substitute_decl(subst, current_scope, global_scope) - ->as_instance(); - if (inst == this) { - // Hmm, nothing to substitute. Make a new instance anyway, so we can - // change the name. - inst = new CPPInstance(*this); - } - assert(inst != nullptr); - inst->_ident = inst->_ident->substitute_decl(subst, current_scope, global_scope); - if (inst->_ident == _ident) { - inst->_ident = new CPPIdentifier(*inst->_ident); - } - inst->_ident->_names.back().set_templ - (new CPPTemplateParameterList(*actual_params)); - - inst->_template_scope = nullptr; - - ((CPPInstance *)this)->_instantiations.insert(Instantiations::value_type(actual_params, inst)); - return inst; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPInstance:: -is_fully_specified() const { - if (_ident != nullptr && !_ident->is_fully_specified()) { - return false; - } - if (_initializer != nullptr && !_initializer->is_fully_specified()) { - return false; - } - return CPPDeclaration::is_fully_specified() && - _type->is_fully_specified(); -} - -/** - * - */ -CPPDeclaration *CPPInstance:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPDeclaration *top = - CPPDeclaration::substitute_decl(subst, current_scope, global_scope); - if (top != this) { - return top; - } - - CPPInstance *rep = new CPPInstance(*this); - CPPDeclaration *new_type = - _type->substitute_decl(subst, current_scope, global_scope); - rep->_type = new_type->as_type(); - - if (rep->_type == nullptr) { - rep->_type = _type; - } - - if (_initializer != nullptr) { - rep->_initializer = - _initializer->substitute_decl(subst, current_scope, global_scope) - ->as_expression(); - } - - if (rep->_type == _type && - rep->_initializer == _initializer) { - delete rep; - rep = this; - } - - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * - */ -void CPPInstance:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - output(out, indent_level, scope, complete, -1); -} - -/** - * The extra parameter comes into play only when we happen to be outputting a - * function prototype. See CPPFunctionType::output(). - */ -void CPPInstance:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete, - int num_default_parameters) const { - assert(_type != nullptr); - - if (_type->is_parameter_expr()) { - // In this case, the whole thing is really an expression, and not an - // instance at all. This can only happen if we parsed an instance - // declaration while we thought we were parsing a function prototype. - out << *_initializer; - return; - } - - if (is_template()) { - get_template_scope()->_parameters.write_formal(out, scope); - indent(out, indent_level); - } - - if (!_attributes.is_empty()) { - out << _attributes << " "; - } - - if (_storage_class & SC_static) { - out << "static "; - } - if (_storage_class & SC_extern) { - out << "extern "; - } - if (_storage_class & SC_c_binding) { - out << "\"C\" "; - } - if (_storage_class & SC_virtual) { - out << "virtual "; - } - if (_storage_class & SC_inline) { - out << "inline "; - } - if (_storage_class & SC_explicit) { - out << "explicit "; - } - if (_storage_class & SC_register) { - out << "register "; - } - if (_storage_class & SC_volatile) { - out << "volatile "; - } - if (_storage_class & SC_mutable) { - out << "mutable "; - } - if (_storage_class & SC_consteval) { - out << "consteval "; - } - if (_storage_class & SC_constexpr) { - out << "constexpr "; - } - if (_storage_class & SC_constinit) { - out << "constinit "; - } - if (_storage_class & SC_thread_local) { - out << "thread_local "; - } - - string name; - if (_ident != nullptr) { - name = _ident->get_local_name(scope); - } - if (_storage_class & SC_parameter_pack) { - name = "..." + name; - } - - if (_type->as_function_type()) { - _type->as_function_type()-> - output_instance(out, indent_level, scope, complete, "", name, - num_default_parameters); - } - else { - _type->output_instance(out, indent_level, scope, complete, "", name); - } - - if (_bit_width != -1) { - out << " : " << _bit_width; - } - - if (_storage_class & SC_pure_virtual) { - out << " = 0"; - } - if (_storage_class & SC_defaulted) { - out << " = default"; - } - if (_storage_class & SC_deleted) { - out << " = delete"; - } - if (_initializer != nullptr) { - out << " = " << *_initializer; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPInstance:: -get_subtype() const { - return ST_instance; -} - -/** - * - */ -CPPInstance *CPPInstance:: -as_instance() { - return this; -} diff --git a/dtool/src/cppparser/cppInstance.h b/dtool/src/cppparser/cppInstance.h deleted file mode 100644 index 8e8c427f52..0000000000 --- a/dtool/src/cppparser/cppInstance.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppInstance.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPINSTANCE_H -#define CPPINSTANCE_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" -#include "cppType.h" -#include "cppTemplateParameterList.h" -#include "cppAttributeList.h" - -class CPPInstanceIdentifier; -class CPPIdentifier; -class CPPParameterList; -class CPPScope; -class CPPExpression; - -/** - * - */ -class CPPInstance : public CPPDeclaration { -public: - // Some of these flags clearly only make sense in certain contexts, e.g. - // for a function or method. - enum StorageClass { - SC_static = 0x0001, - SC_extern = 0x0002, - SC_c_binding = 0x0004, - SC_virtual = 0x0008, - SC_inline = 0x0010, - SC_explicit = 0x0020, - SC_register = 0x0040, - SC_pure_virtual = 0x0080, - SC_volatile = 0x0100, - SC_mutable = 0x0200, - SC_consteval = 0x080000, - SC_constexpr = 0x000400, - SC_constinit = 0x100000, - - // This bit is only set by CPPStructType::check_virtual(). - SC_inherited_virtual = 0x0800, - - // This is a special "storage class" for methods tagged with the BLOCKING - // macro (i.e. the special __blocking keyword). These are methods that - // might block and therefore need to release Python threads for their - // duration. - SC_blocking = 0x1000, - - // And this is for methods tagged with __extension, which declares - // extension methods defined separately from the source code. - SC_extension = 0x2000, - - // These are for =default and =delete functions. - SC_defaulted = 0x4000, - SC_deleted = 0x8000, - - SC_thread_local = 0x10000, - - // This isn't really a storage class. It's only used temporarily by the - // parser, to make parsing specifier sequences a bit easier. - SC_const = 0x20000, - - // Used to indicate that this is a parameter pack. - SC_parameter_pack = 0x40000, - }; - - CPPInstance(CPPType *type, const std::string &name, int storage_class = 0); - CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class = 0); - CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, - int storage_class, const CPPFile &file); - CPPInstance(const CPPInstance ©); - ~CPPInstance(); - - static CPPInstance * - make_typecast_function(CPPInstance *inst, CPPIdentifier *ident, - CPPParameterList *parameters, int function_flags); - - bool operator == (const CPPInstance &other) const; - bool operator != (const CPPInstance &other) const; - bool operator < (const CPPInstance &other) const; - - void set_initializer(CPPExpression *initializer); - void set_alignment(int align); - void set_alignment(CPPExpression *const_expr); - - bool is_scoped() const; - CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - std::string get_simple_name() const; - std::string get_local_name(CPPScope *scope = nullptr) const; - std::string get_fully_scoped_name() const; - - void check_for_constructor(CPPScope *current_scope, CPPScope *global_scope); - - virtual CPPDeclaration * - instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, int num_default_parameters) const; - virtual SubType get_subtype() const; - - virtual CPPInstance *as_instance(); - - CPPType *_type; - CPPIdentifier *_ident; - CPPExpression *_initializer; - - int _storage_class; - int _bit_width; - -private: - typedef std::map Instantiations; - Instantiations _instantiations; -}; - -#endif diff --git a/dtool/src/cppparser/cppInstanceIdentifier.cxx b/dtool/src/cppparser/cppInstanceIdentifier.cxx deleted file mode 100644 index cc32ee8a81..0000000000 --- a/dtool/src/cppparser/cppInstanceIdentifier.cxx +++ /dev/null @@ -1,345 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppInstanceIdentifier.cxx - * @author drose - * @date 1999-10-21 - */ - -#include "cppInstanceIdentifier.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" -#include "cppArrayType.h" -#include "cppConstType.h" -#include "cppFunctionType.h" -#include "cppSimpleType.h" -#include "cppParameterList.h" -#include "cppIdentifier.h" - -/** - * - */ -CPPInstanceIdentifier::Modifier:: -Modifier(CPPInstanceIdentifierType type, CPPAttributeList attr) : - _type(type), - _func_params(nullptr), - _func_flags(0), - _scoping(nullptr), - _expr(nullptr), - _attributes(std::move(attr)) { -} - -/** - * - */ -CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier:: -func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type, - CPPAttributeList attr) { - Modifier mod(IIT_func, std::move(attr)); - mod._func_params = params; - mod._func_flags = flags; - mod._trailing_return_type = trailing_return_type; - return mod; -} - -/** - * - */ -CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier:: -array_type(CPPExpression *expr, CPPAttributeList attr) { - Modifier mod(IIT_array, std::move(attr)); - mod._expr = expr; - return mod; -} - -/** - * - */ -CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier:: -scoped_pointer_type(CPPIdentifier *scoping, CPPAttributeList attr) { - Modifier mod(IIT_scoped_pointer, std::move(attr)); - mod._scoping = scoping; - return mod; -} - -/** - * This is used only for instance declarations that turn out to be have a - * parameter list for an initializer. - */ -CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier:: -initializer_type(CPPParameterList *params) { - Modifier mod(IIT_initializer); - mod._func_params = params; - return mod; -} - -/** - * - */ -CPPInstanceIdentifier:: -CPPInstanceIdentifier(CPPIdentifier *ident) : - _ident(ident), - _bit_width(nullptr), - _packed(false) { -} - -/** - * - */ -CPPInstanceIdentifier:: -CPPInstanceIdentifier(CPPIdentifier *ident, CPPAttributeList attributes) : - _ident(ident), - _attributes(std::move(attributes)), - _bit_width(nullptr), - _packed(false) { -} - -/** - * Unrolls the list of type punctuation on either side of the identifier to - * determine the actual type represented by the identifier, given the - * indicated starting type (that is, the type name written to the left of the - * identifier). - */ -CPPType *CPPInstanceIdentifier:: -unroll_type(CPPType *start_type) { - CPPType *result = r_unroll_type(start_type, _modifiers.begin()); - return result; -} - - -/** - * - */ -void CPPInstanceIdentifier:: -add_modifier(CPPInstanceIdentifierType type, CPPAttributeList attr) { - _modifiers.push_back(Modifier(type, std::move(attr))); -} - -/** - * - */ -void CPPInstanceIdentifier:: -add_func_modifier(CPPParameterList *params, int flags, - CPPType *trailing_return_type, CPPAttributeList attr) { - // As a special hack, if we added a parameter list to an operator function, - // check if the parameter list is empty. If it is, this is really a unary - // operator, so set the unary_op flag. Operators () and [] are never - // considered unary operators. - if (_ident != nullptr && - _ident->get_simple_name().substr(0, 9) == "operator ") { - - if (_ident->get_simple_name() != std::string("operator ()") && - _ident->get_simple_name() != std::string("operator []")) { - if (params->_parameters.empty()) { - flags |= CPPFunctionType::F_unary_op; - } - } - - flags |= CPPFunctionType::F_operator; - } - - if (trailing_return_type != nullptr) { - // Remember whether trailing return type notation was used. - flags |= CPPFunctionType::F_trailing_return_type; - } - - _modifiers.push_back(Modifier::func_type(params, flags, trailing_return_type, std::move(attr))); -} - -/** - * - */ -void CPPInstanceIdentifier:: -add_scoped_pointer_modifier(CPPIdentifier *scoping, CPPAttributeList attr) { - _modifiers.push_back(Modifier::scoped_pointer_type(scoping, std::move(attr))); -} - -/** - * - */ -void CPPInstanceIdentifier:: -add_array_modifier(CPPExpression *expr, CPPAttributeList attr) { - // Special case for operator new[] and delete[]. We're not really adding an - // array modifier to them, but appending [] to the identifier. This is to - // work around a parser ambiguity. - if (_ident != nullptr && (_ident->get_simple_name() == "operator delete" || - _ident->get_simple_name() == "operator new")) { - - _ident->_names.back().append_name("[]"); - } else { - _modifiers.push_back(Modifier::array_type(expr, std::move(attr))); - } -} - -/** - * - */ -void CPPInstanceIdentifier:: -add_initializer_modifier(CPPParameterList *params) { - _modifiers.push_back(Modifier::initializer_type(params)); -} - -/** - * - */ -void CPPInstanceIdentifier:: -add_trailing_return_type(CPPType *type) { - // This is an awkward hack. Improve in the future. - if (!_modifiers.empty()) { - Modifier &mod = _modifiers.back(); - if (mod._type == IIT_func) { - mod._trailing_return_type = type; - mod._func_flags |= CPPFunctionType::F_trailing_return_type; - return; - } - } - std::cerr << "trailing return type can only be added to a function\n"; -} - -/** - * Add attributes to the instance (not the type). - */ -void CPPInstanceIdentifier:: -add_attributes(const CPPAttributeList &attributes) { - _attributes.add_attributes_from(attributes); -} - -/** - * Returns the initializer parameter list that was set for this particular - * instance, e.g. if the instance were: - * - * int foo(0); - * - * this would return the parameter list (0). Returns NULL if the instance did - * not use a parameter list initializer. - */ -CPPParameterList *CPPInstanceIdentifier:: -get_initializer() const { - Modifiers::const_iterator mi; - for (mi = _modifiers.begin(); mi != _modifiers.end(); ++mi) { - const Modifier &mod = (*mi); - if (mod._type == IIT_initializer) { - return mod._func_params; - } - } - - return nullptr; -} - -/** - * - */ -CPPScope *CPPInstanceIdentifier:: -get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - if (_ident == nullptr) { - return current_scope; - } else { - return _ident->get_scope(current_scope, global_scope, error_sink); - } -} - -/** - * The recursive implementation of unroll_type(). - */ -CPPType *CPPInstanceIdentifier:: -r_unroll_type(CPPType *start_type, - CPPInstanceIdentifier::Modifiers::const_iterator mi) { - assert(start_type != nullptr); - - start_type = CPPType::new_type(start_type); - - if (mi == _modifiers.end()) { - return start_type; - } - - const Modifier &mod = (*mi); - ++mi; - - CPPType *result = nullptr; - - switch (mod._type) { - case IIT_pointer: - result = new CPPPointerType(r_unroll_type(start_type, mi)); - break; - - case IIT_reference: - result = new CPPReferenceType(r_unroll_type(start_type, mi), - CPPReferenceType::VC_lvalue); - break; - - case IIT_rvalue_reference: - result = new CPPReferenceType(r_unroll_type(start_type, mi), - CPPReferenceType::VC_rvalue); - break; - - case IIT_scoped_pointer: - { - CPPType *type = r_unroll_type(start_type, mi); - CPPFunctionType *ftype = type->as_function_type(); - if (ftype != nullptr) { - ftype = new CPPFunctionType(*ftype); - ftype->_class_owner = mod._scoping; - ftype->_flags |= CPPFunctionType::F_method_pointer; - type = ftype; - } - result = new CPPPointerType(type); - } - break; - - case IIT_array: - result = new CPPArrayType(r_unroll_type(start_type, mi), - mod._expr); - break; - - case IIT_const: - result = new CPPConstType(r_unroll_type(start_type, mi)); - break; - - case IIT_volatile: - case IIT_restrict: - // Just pass it through for now. - result = r_unroll_type(start_type, mi); - break; - - case IIT_paren: - result = r_unroll_type(start_type, mi); - break; - - case IIT_func: - { - CPPType *return_type = r_unroll_type(start_type, mi); - if (mod._trailing_return_type != nullptr) { - CPPSimpleType *simple_type = return_type->as_simple_type(); - if (simple_type != nullptr && simple_type->_type == CPPSimpleType::T_auto) { - return_type = mod._trailing_return_type; - } else { - std::cerr << "function with trailing return type needs auto\n"; - } - } - result = new CPPFunctionType(return_type, mod._func_params, - mod._func_flags); - } - break; - - case IIT_initializer: - // In this case, we have parsed an instance declaration with a set of - // initializers as a parameter list. We lose the initializers at this - // point, but the instance will put it back again. - result = start_type; - break; - - default: - std::cerr << "Internal error--invalid CPPInstanceIdentifier\n"; - abort(); - } - - result->_attributes = mod._attributes; - - return CPPType::new_type(result); -} diff --git a/dtool/src/cppparser/cppInstanceIdentifier.h b/dtool/src/cppparser/cppInstanceIdentifier.h deleted file mode 100644 index 21117a8aea..0000000000 --- a/dtool/src/cppparser/cppInstanceIdentifier.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppInstanceIdentifier.h - * @author drose - * @date 1999-10-21 - */ - -#ifndef CPPINSTANCEIDENTIFIER_H -#define CPPINSTANCEIDENTIFIER_H - -#include "dtoolbase.h" -#include "cppAttributeList.h" - -#include -#include - -class CPPIdentifier; -class CPPParameterList; -class CPPType; -class CPPExpression; -class CPPScope; -class CPPPreprocessor; - -enum CPPInstanceIdentifierType { - IIT_pointer, - IIT_reference, - IIT_rvalue_reference, - IIT_scoped_pointer, - IIT_array, - IIT_const, - IIT_volatile, - IIT_restrict, - IIT_paren, - IIT_func, - IIT_initializer, -}; - -/** - * This class is used in parser.y to build up a variable instance definition. - * An instance is something like 'int *&a'; the InstanceIdentifier stores - * everything to the right of the typename. Later this can be passed to - * make_instance() to construct a CPPInstance. - */ -class CPPInstanceIdentifier { -public: - CPPInstanceIdentifier(CPPIdentifier *ident); - CPPInstanceIdentifier(CPPIdentifier *ident, CPPAttributeList attributes); - - CPPType *unroll_type(CPPType *start_type); - - void add_modifier(CPPInstanceIdentifierType type, - CPPAttributeList attr = CPPAttributeList()); - void add_func_modifier(CPPParameterList *params, int flags, - CPPType *trailing_return_type = nullptr, - CPPAttributeList attr = CPPAttributeList()); - void add_scoped_pointer_modifier(CPPIdentifier *scoping, - CPPAttributeList attr = CPPAttributeList()); - void add_array_modifier(CPPExpression *expr, - CPPAttributeList attr = CPPAttributeList()); - void add_initializer_modifier(CPPParameterList *params); - - void add_trailing_return_type(CPPType *type); - - void add_attributes(const CPPAttributeList &attributes); - - CPPParameterList *get_initializer() const; - - CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - CPPIdentifier *_ident; - - class Modifier { - public: - Modifier(CPPInstanceIdentifierType type, - CPPAttributeList attr = CPPAttributeList()); - static Modifier func_type(CPPParameterList *params, int flags, - CPPType *trailing_return_type, - CPPAttributeList attr); - static Modifier array_type(CPPExpression *expr, CPPAttributeList attr); - static Modifier scoped_pointer_type(CPPIdentifier *scoping, - CPPAttributeList attr); - static Modifier initializer_type(CPPParameterList *params); - - CPPInstanceIdentifierType _type; - CPPParameterList *_func_params; - int _func_flags; - CPPIdentifier *_scoping; - CPPExpression *_expr; - CPPType *_trailing_return_type; - CPPAttributeList _attributes; - }; - typedef std::vector Modifiers; - Modifiers _modifiers; - - CPPAttributeList _attributes; - - // If not null, indicates a bitfield - CPPExpression *_bit_width; - - // Indicates a parameter pack - bool _packed; - -private: - CPPType * - r_unroll_type(CPPType *start_type, Modifiers::const_iterator mi); -}; - -#endif diff --git a/dtool/src/cppparser/cppMakeProperty.cxx b/dtool/src/cppparser/cppMakeProperty.cxx deleted file mode 100644 index 1846092eaa..0000000000 --- a/dtool/src/cppparser/cppMakeProperty.cxx +++ /dev/null @@ -1,122 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppMakeProperty.cxx - * @author rdb - * @date 2014-09-18 - */ - -#include "cppMakeProperty.h" -#include "cppFunctionGroup.h" - -/** - * - */ -CPPMakeProperty:: -CPPMakeProperty(CPPIdentifier *ident, Type type, - CPPScope *current_scope, const CPPFile &file) : - CPPDeclaration(file), - _ident(ident), - _type(type), - _length_function(nullptr), - _has_function(nullptr), - _get_function(nullptr), - _set_function(nullptr), - _clear_function(nullptr), - _del_function(nullptr), - _insert_function(nullptr), - _get_key_function(nullptr) -{ - _ident->_native_scope = current_scope; -} - -/** - * - */ -std::string CPPMakeProperty:: -get_simple_name() const { - return _ident->get_simple_name(); -} - -/** - * - */ -std::string CPPMakeProperty:: -get_local_name(CPPScope *scope) const { - return _ident->get_local_name(scope); -} - -/** - * - */ -std::string CPPMakeProperty:: -get_fully_scoped_name() const { - return _ident->get_fully_scoped_name(); -} - -/** - * - */ -void CPPMakeProperty:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (_length_function != nullptr) { - out << "__make_seq_property"; - } else { - out << "__make_property"; - } - - if (_has_function != nullptr) { - out.put('2'); - } - - out << "(" << _ident->get_local_name(scope); - - if (_length_function != nullptr) { - out << ", " << _length_function->_name; - } - - if (_has_function != nullptr) { - out << ", " << _has_function->_name; - } - - out << ", " << _get_function->_name; - - if (_set_function != nullptr) { - out << ", " << _set_function->_name; - } - - if (_clear_function != nullptr) { - out << ", " << _clear_function->_name; - } - - if (_del_function != nullptr) { - out << ", " << _del_function->_name; - } - - if (_insert_function != nullptr) { - out << ", " << _insert_function->_name; - } - - out << ");"; -} - -/** - * - */ -CPPDeclaration::SubType CPPMakeProperty:: -get_subtype() const { - return ST_make_property; -} - -/** - * - */ -CPPMakeProperty *CPPMakeProperty:: -as_make_property() { - return this; -} diff --git a/dtool/src/cppparser/cppMakeProperty.h b/dtool/src/cppparser/cppMakeProperty.h deleted file mode 100644 index 2967ee3b09..0000000000 --- a/dtool/src/cppparser/cppMakeProperty.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppMakeProperty.h - * @author rdb - * @date 2014-09-18 - */ - -#ifndef CPPMAKEPROPERTY_H -#define CPPMAKEPROPERTY_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" -#include "cppIdentifier.h" - -/** - * This is a MAKE_PROPERTY() declaration appearing within a class body. It - * means to generate a property within Python, replacing (for instance) - * get_something()/set_something() with a synthetic 'something' attribute. - * - * This is an example of a simple property (MAKE_PROPERTY is defined as - * the built-in __make_property): - * @@code - * Thing get_thing() const; - * void set_thing(const Thing &); - * - * MAKE_PROPERTY(thing, get_thing, set_thing); - * @@endcode - * The setter may be omitted to make the property read-only. - * - * There is also a secondary macro that allows the property to be set to a - * cleared state using separate clear functions. In the scripting language, - * this would be represented by a "null" value, or an "optional" construct in - * languages that have no notion of a null value. - * - * @@code - * bool has_thing() const; - * Thing get_thing() const; - * void set_thing(const Thing &); - * void clear_thing(); - * MAKE_PROPERTY2(thing, has_thing, get_thing, set_thing, clear_thing); - * @@endcode - * As with MAKE_PROPERTY, both the setter and clearer can be omitted to create - * a read-only property. - * - * Thirdly, there is a variant called MAKE_SEQ_PROPERTY. It takes a length - * function as argument and the getter and setter take an index as first - * argument: - * @@code - * size_t get_num_things() const; - * Thing &get_thing(size_t i) const; - * void set_thing(size_t i, Thing value) const; - * void remove_thing(size_t i) const; - * - * MAKE_SEQ_PROPERTY(get_num_things, get_thing, set_thing, remove_thing); - * @@endcode - * - * Lastly, there is the possibility to have properties with key/value - * associations, often called a "map" or "dictionary" in scripting languages: - * @@code - * bool has_thing(string key) const; - * Thing &get_thing(string key) const; - * void set_thing(string key, Thing value) const; - * void clear_thing(string key) const; - * - * MAKE_MAP_PROPERTY(things, has_thing, get_thing, set_thing, clear_thing); - * @@endcode - * You may also replace the "has" function with a "find" function that returns - * an index. If the returned index is negative (or in the case of an unsigned - * integer, the maximum value), the item is assumed not to be present in the - * mapping. - * - * It is also possible to use both MAKE_SEQ_PROPERTY and MAKE_MAP_PROPERTY on - * the same property name. This implies that this property has both a - * sequence and mapping interface. - */ -class CPPMakeProperty : public CPPDeclaration { -public: - enum Type { - T_normal = 0x0, - T_sequence = 0x1, - T_mapping = 0x2, - }; - - CPPMakeProperty(CPPIdentifier *ident, Type type, - CPPScope *current_scope, const CPPFile &file); - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - - virtual SubType get_subtype() const; - virtual CPPMakeProperty *as_make_property(); - - CPPIdentifier *_ident; - Type _type; - CPPFunctionGroup *_length_function; - CPPFunctionGroup *_has_function; - CPPFunctionGroup *_get_function; - CPPFunctionGroup *_set_function; - CPPFunctionGroup *_clear_function; - CPPFunctionGroup *_del_function; - CPPFunctionGroup *_insert_function; - CPPFunctionGroup *_get_key_function; -}; - -#endif diff --git a/dtool/src/cppparser/cppMakeSeq.cxx b/dtool/src/cppparser/cppMakeSeq.cxx deleted file mode 100644 index b032d367bb..0000000000 --- a/dtool/src/cppparser/cppMakeSeq.cxx +++ /dev/null @@ -1,81 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppMakeSeq.cxx - * @author drose - * @date 2008-11-06 - */ - -#include "cppMakeSeq.h" - -/** - * - */ -CPPMakeSeq:: -CPPMakeSeq(CPPIdentifier *ident, - CPPFunctionGroup *length_getter, - CPPFunctionGroup *element_getter, - CPPScope *current_scope, const CPPFile &file) : - CPPDeclaration(file), - _ident(ident), - _length_getter(length_getter), - _element_getter(element_getter) -{ - _ident->_native_scope = current_scope; -} - -/** - * - */ -std::string CPPMakeSeq:: -get_simple_name() const { - return _ident->get_simple_name(); -} - -/** - * - */ -std::string CPPMakeSeq:: -get_local_name(CPPScope *scope) const { - return _ident->get_local_name(scope); -} - -/** - * - */ -std::string CPPMakeSeq:: -get_fully_scoped_name() const { - return _ident->get_fully_scoped_name(); -} - -/** - * - */ -void CPPMakeSeq:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - out << "__make_seq(" << _ident->get_local_name(scope) - << ", " << _length_getter->_name - << ", " << _element_getter->_name - << ");"; -} - -/** - * - */ -CPPDeclaration::SubType CPPMakeSeq:: -get_subtype() const { - return ST_make_seq; -} - -/** - * - */ -CPPMakeSeq *CPPMakeSeq:: -as_make_seq() { - return this; -} diff --git a/dtool/src/cppparser/cppMakeSeq.h b/dtool/src/cppparser/cppMakeSeq.h deleted file mode 100644 index 1db722d9bb..0000000000 --- a/dtool/src/cppparser/cppMakeSeq.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppMakeSeq.h - * @author drose - * @date 2008-11-06 - */ - -#ifndef CPPMAKESEQ_H -#define CPPMAKESEQ_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" -#include "cppIdentifier.h" -#include "cppFunctionGroup.h" - -/** - * This is a MAKE_SEQ() declaration appearing within a class body. It means - * to generate a sequence method within Python, replacing (for instance) - * get_num_nodes()/get_node(n) with a synthetic get_nodes() method. - */ -class CPPMakeSeq : public CPPDeclaration { -public: - CPPMakeSeq(CPPIdentifier *ident, - CPPFunctionGroup *length_getter, - CPPFunctionGroup *element_getter, - CPPScope *current_scope, const CPPFile &file); - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - - virtual SubType get_subtype() const; - virtual CPPMakeSeq *as_make_seq(); - - CPPIdentifier *_ident; - CPPFunctionGroup *_length_getter; - CPPFunctionGroup *_element_getter; -}; - -#endif diff --git a/dtool/src/cppparser/cppManifest.cxx b/dtool/src/cppparser/cppManifest.cxx deleted file mode 100644 index 4a036f4d7a..0000000000 --- a/dtool/src/cppparser/cppManifest.cxx +++ /dev/null @@ -1,672 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppManifest.cxx - * @author drose - * @date 1999-10-22 - */ - -#include "cppManifest.h" -#include "cppExpression.h" -#include "cppPreprocessor.h" - -#include - -using std::string; - -/** - * - */ -CPPManifest::ExpansionNode:: -ExpansionNode(int parm_number, bool stringify, bool paste) : - _parm_number(parm_number), - _expand(!stringify && !paste), - _stringify(stringify), - _paste(paste), - _optional(false) -{ -} - -/** - * - */ -CPPManifest::ExpansionNode:: -ExpansionNode(const string &str, bool paste) : - _parm_number(-1), - _expand(!paste), - _stringify(false), - _paste(paste), - _optional(false), - _str(str) -{ -} - -/** - * - */ -CPPManifest::ExpansionNode:: -ExpansionNode(Expansion nested, bool stringify, bool paste, bool optional) : - _parm_number(-1), - _expand(!stringify && !paste), - _stringify(stringify), - _paste(paste), - _optional(optional), - _nested(std::move(nested)) -{ -} - -/** - * - */ -bool CPPManifest::ExpansionNode:: -operator ==(const ExpansionNode &other) const { - return _parm_number == other._parm_number - && _expand == other._expand - && _stringify == other._stringify - && _paste == other._paste - && _optional == other._optional - && _str == other._str - && _nested == other._nested; -} - -/** - * Creates a manifest from a preprocessor definition. - */ -CPPManifest:: -CPPManifest(const CPPPreprocessor &parser, const string &args, const cppyyltype &loc) : - _parser(parser), - _variadic_param(-1), - _loc(loc), - _expr(nullptr), - _vis(V_public) -{ - assert(!args.empty()); - assert(!isspace(args[0])); - - // First, identify the manifest name. - size_t p = 0; - while (p < args.size() && !isspace(args[p]) && args[p] != '(') { - p++; - } - - _name = args.substr(0, p); - - vector_string parameter_names; - - if (args[p] == '(') { - // Hmm, parameters. - _has_parameters = true; - parse_parameters(args, p, parameter_names); - _num_parameters = parameter_names.size(); - - p++; - } else { - _has_parameters = false; - _num_parameters = 0; - } - - // Now identify the expansion. Skip whitespace. - while (p < args.size() && isspace(args[p])) { - p++; - } - - save_expansion(_expansion, args.substr(p), parameter_names); -} - -/** - * Creates a custom manifest definition, for example as specified from a - * command-line -D option. - */ -CPPManifest:: -CPPManifest(const CPPPreprocessor &parser, const string ¯o, const string &definition) : - _parser(parser), - _variadic_param(-1), - _expr(nullptr), - _vis(V_public) -{ - _loc.first_line = 0; - _loc.first_column = 0; - _loc.last_line = 0; - _loc.last_column = 0; - - assert(!macro.empty()); - assert(!isspace(macro[0])); - - // First, identify the manifest name. - size_t p = 0; - while (p < macro.size() && !isspace(macro[p]) && macro[p] != '(') { - p++; - } - - _name = macro.substr(0, p); - - vector_string parameter_names; - - if (macro[p] == '(') { - // Hmm, parameters. - _has_parameters = true; - parse_parameters(macro, p, parameter_names); - _num_parameters = parameter_names.size(); - - p++; - } else { - _has_parameters = false; - _num_parameters = 0; - } - - save_expansion(_expansion, definition, parameter_names); -} - -/** - * - */ -CPPManifest:: -~CPPManifest() { - delete _expr; -} - -/** - * This implements the stringification operator, #. - */ -string CPPManifest:: -stringify(const string &source) { - string result("\""); - - enum { - S_escaped = 0x01, - S_single_quoted = 0x02, - S_double_quoted = 0x04, - S_quoted = 0x06, - }; - int state = 0; - - string::const_iterator it; - for (it = source.begin(); it != source.end(); ++it) { - char c = *it; - - if ((state & S_escaped) == 0) { - switch (c) { - case '\\': - if (state & S_quoted) { - state |= S_escaped; - result += '\\'; - } - break; - - case '\'': - state ^= S_single_quoted; - break; - - case '"': - state ^= S_double_quoted; - result += '\\'; - break; - } - } else { - if (c == '\\' || c == '"') { - result += '\\'; - } - state &= ~S_escaped; - } - - result += c; - } - - result += '"'; - return result; -} - -/** - * - */ -void CPPManifest:: -extract_args(vector_string &args, const string &expr, size_t &p) const { - // Skip whitespace till paren. - while (p < expr.size() && isspace(expr[p])) { - p++; - } - if (p >= expr.size() || expr[p] != '(') { - // No paren, so we have only one arg. - size_t q = p; - while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { - p++; - } - args.push_back(expr.substr(q, p - q)); - } - else if (expr[p] == '"' || expr[p] == '\'') { - // Quoted string or character. - int quote_mark = expr[p]; - p++; - while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { - if (expr[p] == '\\') { - p++; - } - if (p < expr.size()) { - p++; - } - } - p++; - } - else { - // Skip paren. - p++; - int paren_level = 1; - size_t q = p; - while (p < expr.size()) { - if (expr[p] == ',' && paren_level == 1) { - // Back up to strip any trailing whitespace. - size_t r = p; - while (r > q && isspace(expr[r - 1])) { - --r; - } - args.push_back(expr.substr(q, r - q)); - q = p+1; - } - else if (expr[p] == '"' || expr[p] == '\'') { - // Quoted string or character. - int quote_mark = expr[p]; - p++; - while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { - if (expr[p] == '\\') { - p++; - } - if (p < expr.size()) { - p++; - } - } - } - else if (expr[p] == '(') { - ++paren_level; - } - else if (expr[p] == ')') { - --paren_level; - if (paren_level == 0) { - break; - } - } - else if (isspace(expr[p])) { - // Skip whitespace at the beginning. - if (q == p) { - q++; - } - } - p++; - } - { - // Back up to strip any trailing whitespace. - size_t r = p; - while (r > q && isspace(expr[r - 1])) { - --r; - } - if (!args.empty() || r > q) { - args.push_back(expr.substr(q, r - q)); - } - } - - if (p < expr.size() && expr[p] == ')') { - p++; - } - } - - if ((int)args.size() < _num_parameters) { - _parser.warning("Not enough arguments for manifest " + _name); - } - else if (_variadic_param < 0 && (int)args.size() > _num_parameters) { - _parser.warning("Too many arguments for manifest " + _name); - } -} - -/** - * - */ -string CPPManifest:: -expand(const vector_string &args, bool expand_undefined, const Ignores &ignores) const { - return r_expand(_expansion, args, expand_undefined, ignores); -} - -/** - * Returns the type of the manifest, if it is known, or NULL if the type - * cannot be determined. - */ -CPPType *CPPManifest:: -determine_type() const { - if (_expr != nullptr) { - return _expr->determine_type(); - } - return nullptr; -} - -/** - * Returns true if the macro definitions are equal. - */ -bool CPPManifest:: -is_equal(const CPPManifest *other) const { - if (this == other) { - return true; - } - if (_name != other->_name) { - return false; - } - if (_has_parameters != other->_has_parameters) { - return false; - } - if (_num_parameters != other->_num_parameters) { - return false; - } - if (_variadic_param != other->_variadic_param) { - return false; - } - if (_expansion != other->_expansion) { - return false; - } - return true; -} - -/** - * - */ -void CPPManifest:: -output(std::ostream &out) const { - out << _name; - - if (_has_parameters) { - out << "("; - if (_num_parameters > 0) { - if (_variadic_param == 0) { - out << "..."; - } else { - out << "$1"; - } - - for (size_t i = 1; i < _num_parameters; ++i) { - if (_variadic_param == (int)i) { - out << ", ..."; - } else { - out << ", $" << i + 1; - } - } - } - out << ")"; - } - - Expansion::const_iterator ei; - for (ei = _expansion.begin(); ei != _expansion.end(); ++ei) { - if ((*ei)._paste) { - out << " ## "; - } else { - out << " "; - } - - if ((*ei)._stringify) { - out << "#"; - } - if ((*ei)._parm_number >= 0) { - if ((*ei)._parm_number == _variadic_param) { - out << "__VA_ARGS__"; - } else { - out << "$" << (*ei)._parm_number + 1; - } - } - if ((*ei)._optional) { - out << "__VA_OPT__("; - } - if (!(*ei)._str.empty()) { - out << (*ei)._str; - } - if ((*ei)._optional) { - out << ")"; - } - } -} - -/** - * - */ -void CPPManifest:: -parse_parameters(const string &args, size_t &p, - vector_string ¶meter_names) { - assert(p < args.size()); - assert(args[p] == '('); - - p++; - while (p < args.size() && isspace(args[p])) { - p++; - } - - while (p < args.size() && args[p] != ')') { - // Here's the beginning of a parm. - size_t q = p; - while (p < args.size() && !isspace(args[p]) && - args[p] != ')' && args[p] != ',') { - p++; - } - - // Check if it's a variadic parameter by checking if it ends with "...". - // This picks up both C99-style variadic macros and GCC-style variadic - // macros. - if (p - q >= 3 && args.compare(p - 3, 3, "...") == 0) { - _variadic_param = parameter_names.size(); - parameter_names.push_back(args.substr(q, p - q - 3)); - } else { - parameter_names.push_back(args.substr(q, p - q)); - } - - // Skip whitespace after the parameter name. - while (p < args.size() && isspace(args[p])) { - p++; - } - - if (p < args.size() && args[p] == ',') { - p++; - // Skip whitespace after a comma. - while (p < args.size() && isspace(args[p])) { - p++; - } - } - } -} - -/** - * - */ -void CPPManifest:: -save_expansion(Expansion &expansion, const string &exp, const vector_string ¶meter_names) { - // Walk through the expansion string. For each substring that is an - // identifier, check it against parameter_names. - size_t p = 0; - size_t last = 0; - bool stringify = false; - bool paste = false; - while (p < exp.size()) { - if (isalpha(exp[p]) || exp[p] == '_') { - // Here's the start of an identifier. Find the end of it. - size_t q = p; - p++; - while (p < exp.size() && (isalnum(exp[p]) || exp[p] == '_')) { - p++; - } - - string ident = exp.substr(q, p - q); - - // Is this identifier one of our parameters? - int pnum = -1; - - if (ident == "__VA_ARGS__") { - // C99-style variadics, ie. #define macro(...) __VA_ARGS__ - pnum = _variadic_param; - - } else if (ident == "__VA_OPT__") { - // Optional expansion, only expands if __VA_ARGS__ is non-empty - while (p < exp.size() && isspace(exp[p])) { - ++p; - } - if (p < exp.size() && exp[p] == '(') { - int start = ++p; - int nesting = 1; - while (p < exp.size() && nesting > 0) { - if (exp[p] == '(') { - ++nesting; - } - else if (exp[p] == ')') { - --nesting; - } - ++p; - } - - if (last != q) { - expansion.push_back(ExpansionNode(exp.substr(last, q - last), paste)); - paste = false; - } - - // Store this as a nested expansion, because the whole thing may be - // stringified as a whole. - Expansion nested; - save_expansion(nested, exp.substr(start, p - 1 - start), parameter_names); - expansion.push_back(ExpansionNode(std::move(nested), stringify, paste, true)); - stringify = false; - paste = false; - last = p; - continue; - } - - } else { - for (int i = 0; pnum == -1 && i < (int)parameter_names.size(); ++i) { - const string &pname = parameter_names[i]; - if (pname == ident) { - pnum = i; - } - } - } - - if (pnum != -1) { - // Yep! - if (last != q) { - expansion.push_back(ExpansionNode(exp.substr(last, q - last), paste)); - paste = false; - } - expansion.push_back(ExpansionNode(pnum, stringify, paste)); - stringify = false; - paste = false; - last = p; - } - } else if (exp[p] == '#') { - // This may be a stringification operator. - if (last != p) { - expansion.push_back(ExpansionNode(exp.substr(last, p - last), paste)); - paste = false; - } - - ++p; - - if (p < exp.size() && exp[p] == '#') { - // Woah, this is a token-pasting operator. - paste = true; - if (!expansion.empty()) { - // The previous expansion shouldn't be expanded. - expansion.back()._expand = false; - } - ++p; - } else { - // Mark that the next argument should be stringified. - stringify = true; - } - last = p; - - } else if (isspace(exp[p])) { - if (last != p) { - expansion.push_back(ExpansionNode(exp.substr(last, p - last), paste)); - paste = false; - } - - ++p; - last = p; - - } else { - ++p; - } - } - - if (last != p) { - expansion.push_back(ExpansionNode(exp.substr(last, p - last), paste)); - } -} - -/** - * - */ -string CPPManifest:: -r_expand(const Expansion &expansion, const vector_string &args, - bool expand_undefined, const Ignores &ignores) const { - std::string result; - - for (const ExpansionNode &node : expansion) { - if (node._parm_number >= 0) { - int i = node._parm_number; - - string subst; - if (i < (int)args.size()) { - subst = args[i]; - - if (i == _variadic_param) { - for (++i; i < (int)args.size(); ++i) { - subst += ", " + args[i]; - } - } - if (node._stringify) { - subst = stringify(subst); - } - } - else if (i == _variadic_param && node._paste) { - // Special case GCC behavior: if __VA_ARGS__ is pasted to a comma and - // no arguments are passed, the comma is removed. MSVC does this - // automatically. Not sure if we should allow MSVC behavior as well. - if (!result.empty() && *result.rbegin() == ',') { - result.resize(result.size() - 1); - } - } - - if (node._expand) { - _parser.expand_manifests(subst, expand_undefined, ignores); - } - - if (!subst.empty()) { - if (result.empty() || node._paste || result.back() == '(') { - result += subst; - } else { - result += ' '; - result += subst; - } - } - } - if (!node._str.empty()) { - if (result.empty() || node._paste || node._str[0] == ',' || node._str[0] == ')') { - result += node._str; - } else { - result += ' '; - result += node._str; - } - } - if (!node._nested.empty()) { - string nested_result; - if (node._optional && args.size() >= _num_parameters) { - nested_result = r_expand(node._nested, args, expand_undefined, ignores); - } - if (node._stringify) { - nested_result = stringify(nested_result); - } - if (result.empty() || node._paste) { - result += nested_result; - } else { - result += ' '; - result += nested_result; - } - } - } - - return result; -} diff --git a/dtool/src/cppparser/cppManifest.h b/dtool/src/cppparser/cppManifest.h deleted file mode 100644 index f1e4902ab1..0000000000 --- a/dtool/src/cppparser/cppManifest.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppManifest.h - * @author drose - * @date 1999-10-22 - */ - -#ifndef CPPMANIFEST_H -#define CPPMANIFEST_H - -#include "dtoolbase.h" - -#include "cppFile.h" -#include "cppVisibility.h" -#include "cppBisonDefs.h" - -#include "vector_string.h" -#include - -class CPPExpression; -class CPPType; - -/** - * - */ -class CPPManifest { -public: - typedef std::unordered_set Ignores; - - CPPManifest(const CPPPreprocessor &parser, const std::string &args, const cppyyltype &loc); - CPPManifest(const CPPPreprocessor &parser, const std::string ¯o, const std::string &definition); - ~CPPManifest(); - - static std::string stringify(const std::string &source); - void extract_args(vector_string &args, const std::string &expr, size_t &p) const; - std::string expand(const vector_string &args = vector_string(), - bool expand_undefined = false, - const Ignores &ignores = Ignores()) const; - - - CPPType *determine_type() const; - - bool is_equal(const CPPManifest *other) const; - void output(std::ostream &out) const; - - const CPPPreprocessor &_parser; - std::string _name; - bool _has_parameters; - size_t _num_parameters; - int _variadic_param; - cppyyltype _loc; - CPPExpression *_expr; - - // Manifests don't have a visibility in the normal sense. Normally this - // will be V_public. But a manifest that is defined between __begin_publish - // and __end_publish will have a visibility of V_published. - CPPVisibility _vis; - -private: - class ExpansionNode { - public: - ExpansionNode(int parm_number, bool stringify, bool paste); - ExpansionNode(const std::string &str, bool paste = false); - ExpansionNode(std::vector nested, bool stringify = false, bool paste = false, bool optional = false); - - bool operator ==(const ExpansionNode &other) const; - - int _parm_number; - bool _expand; - bool _stringify; - bool _paste; - bool _optional; - std::string _str; - std::vector _nested; - }; - typedef std::vector Expansion; - - void parse_parameters(const std::string &args, size_t &p, - vector_string ¶meter_names); - void save_expansion(Expansion &expansion, const std::string &exp, - const vector_string ¶meter_names); - - std::string r_expand(const Expansion &expansion, const vector_string &args, - bool expand_undefined, const Ignores &ignores) const; - - Expansion _expansion; -}; - -inline std::ostream &operator << (std::ostream &out, const CPPManifest &manifest) { - manifest.output(out); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppNameComponent.cxx b/dtool/src/cppparser/cppNameComponent.cxx deleted file mode 100644 index 1c8e4df88b..0000000000 --- a/dtool/src/cppparser/cppNameComponent.cxx +++ /dev/null @@ -1,167 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppNameComponent.cxx - * @author drose - * @date 1999-11-12 - */ - -#include "cppNameComponent.h" -#include "cppTemplateParameterList.h" - -using std::string; - -/** - * - */ -CPPNameComponent:: -CPPNameComponent(const string &name) : - _name(name) -{ - _templ = nullptr; -} - -/** - * - */ -bool CPPNameComponent:: -operator == (const CPPNameComponent &other) const { - if (_name != other._name) { - return false; - } - if (_templ == nullptr && other._templ == nullptr) { - return true; - } - if (_templ == nullptr || other._templ == nullptr) { - return false; - } - if (*_templ != *other._templ) { - return false; - } - - return true; -} - -/** - * - */ -bool CPPNameComponent:: -operator != (const CPPNameComponent &other) const { - return !(*this == other); -} - -/** - * - */ -bool CPPNameComponent:: -operator < (const CPPNameComponent &other) const { - if (_name != other._name) { - return _name < other._name; - } - if (_templ == nullptr && other._templ == nullptr) { - return false; - } - if (_templ == nullptr || other._templ == nullptr) { - return _templ < other._templ; - } - return (*_templ) < (*other._templ); -} - -/** - * - */ -string CPPNameComponent:: -get_name() const { - return _name; -} - -/** - * - */ -string CPPNameComponent:: -get_name_with_templ(CPPScope *scope) const { - std::ostringstream strm; - strm << _name; - if (_templ != nullptr) { - strm << "< "; - _templ->output(strm, scope); - strm << " >"; - } - return strm.str(); -} - -/** - * - */ -CPPTemplateParameterList *CPPNameComponent:: -get_templ() const { - return _templ; -} - -/** - * - */ -bool CPPNameComponent:: -empty() const { - return _name.empty(); -} - -/** - * - */ -bool CPPNameComponent:: -has_templ() const { - return _templ != nullptr; -} - -/** - * Returns true if the name component includes a template parameter list that - * includes some not-yet-defined type. - */ -bool CPPNameComponent:: -is_tbd() const { - if (_templ != nullptr) { - return _templ->is_tbd(); - } - return false; -} - -/** - * - */ -void CPPNameComponent:: -set_name(const string &name) { - _name = name; -} - -/** - * - */ -void CPPNameComponent:: -append_name(const string &name) { - _name += name; -} - -/** - * - */ -void CPPNameComponent:: -set_templ(CPPTemplateParameterList *templ) { - _templ = templ; -} - -/** - * - */ -void CPPNameComponent:: -output(std::ostream &out) const { - out << _name; - if (_templ != nullptr) { - out << "< " << *_templ << " >"; - } -} diff --git a/dtool/src/cppparser/cppNameComponent.h b/dtool/src/cppparser/cppNameComponent.h deleted file mode 100644 index a33de22a39..0000000000 --- a/dtool/src/cppparser/cppNameComponent.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppNameComponent.h - * @author drose - * @date 1999-11-12 - */ - -#ifndef CPPNAMECOMPONENT_H -#define CPPNAMECOMPONENT_H - -#include "dtoolbase.h" -#include "cppBisonDefs.h" - -#include - -class CPPTemplateParameterList; -class CPPScope; - -class CPPNameComponent { -public: - CPPNameComponent(const std::string &name); - bool operator == (const CPPNameComponent &other) const; - bool operator != (const CPPNameComponent &other) const; - bool operator < (const CPPNameComponent &other) const; - - std::string get_name() const; - std::string get_name_with_templ(CPPScope *scope = nullptr) const; - CPPTemplateParameterList *get_templ() const; - bool empty() const; - bool has_templ() const; - - bool is_tbd() const; - - void set_name(const std::string &name); - void append_name(const std::string &name); - void set_templ(CPPTemplateParameterList *templ); - - void output(std::ostream &out) const; - -private: - std::string _name; - CPPTemplateParameterList *_templ; -}; - -inline std::ostream &operator << (std::ostream &out, const CPPNameComponent &name) { - name.output(out); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppNamespace.cxx b/dtool/src/cppparser/cppNamespace.cxx deleted file mode 100644 index ae37bced70..0000000000 --- a/dtool/src/cppparser/cppNamespace.cxx +++ /dev/null @@ -1,116 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppNamespace.cxx - * @author drose - * @date 1999-11-16 - */ - -#include "cppNamespace.h" -#include "cppIdentifier.h" -#include "cppScope.h" -#include "indent.h" - -/** - * - */ -CPPNamespace:: -CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file, - CPPAttributeList attr) : - CPPDeclaration(file, std::move(attr)), - _is_inline(false), - _ident(ident), - _scope(scope) -{ -} - -/** - * - */ -std::string CPPNamespace:: -get_simple_name() const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_simple_name(); -} - -/** - * - */ -std::string CPPNamespace:: -get_local_name(CPPScope *scope) const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_local_name(scope); -} - -/** - * - */ -std::string CPPNamespace:: -get_fully_scoped_name() const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_fully_scoped_name(); -} - -/** - * - */ -CPPScope *CPPNamespace:: -get_scope() const { - return _scope; -} - -/** - * - */ -void CPPNamespace:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (_is_inline) { - out << "inline "; - } - out << "namespace "; - - if (!complete && _ident != nullptr) { - // If we have a name, use it. - out << "namespace " << _ident->get_local_name(scope); - } - else { - if (!_attributes.is_empty()) { - out << _attributes << " "; - } - if (_ident != nullptr) { - out << _ident->get_local_name(scope) << " {\n"; - } else { - out << "{\n"; - } - - _scope->write(out, indent_level + 2, _scope); - indent(out, indent_level) << "}"; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPNamespace:: -get_subtype() const { - return ST_namespace; -} - -/** - * - */ -CPPNamespace *CPPNamespace:: -as_namespace() { - return this; -} diff --git a/dtool/src/cppparser/cppNamespace.h b/dtool/src/cppparser/cppNamespace.h deleted file mode 100644 index d8b3e7bd21..0000000000 --- a/dtool/src/cppparser/cppNamespace.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppNamespace.h - * @author drose - * @date 1999-11-16 - */ - -#ifndef CPPNAMESPACE_H -#define CPPNAMESPACE_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -class CPPIdentifier; -class CPPScope; - -/** - * - */ -class CPPNamespace : public CPPDeclaration { -public: - CPPNamespace(CPPIdentifier *ident, CPPScope *scope, - const CPPFile &file, CPPAttributeList attr = CPPAttributeList()); - - std::string get_simple_name() const; - std::string get_local_name(CPPScope *scope = nullptr) const; - std::string get_fully_scoped_name() const; - CPPScope *get_scope() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPNamespace *as_namespace(); - - // We can't call this _inline since that would clash with an MSVC built-in - // keyword declaration. - bool _is_inline; - -private: - CPPIdentifier *_ident; - CPPScope *_scope; -}; - -#endif diff --git a/dtool/src/cppparser/cppParameterList.cxx b/dtool/src/cppparser/cppParameterList.cxx deleted file mode 100644 index 4fc5198b6e..0000000000 --- a/dtool/src/cppparser/cppParameterList.cxx +++ /dev/null @@ -1,239 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppParameterList.cxx - * @author drose - * @date 1999-10-21 - */ - -#include "cppParameterList.h" -#include "cppInstance.h" - -/** - * - */ -CPPParameterList:: -CPPParameterList() { - _includes_ellipsis = false; -} - -/** - * This is similar to operator == except it is more forgiving: it is true if - * only the length and order of types is the same, never minding the instance - * names or initial values. - */ -bool CPPParameterList:: -is_equivalent(const CPPParameterList &other) const { - if (_includes_ellipsis != other._includes_ellipsis) { - return false; - } - if (_parameters.size() != other._parameters.size()) { - return false; - } - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (!_parameters[i]->_type->is_equivalent(*other._parameters[i]->_type)) { - return false; - } - } - return true; -} - -/** - * - */ -bool CPPParameterList:: -operator == (const CPPParameterList &other) const { - if (_includes_ellipsis != other._includes_ellipsis) { - return false; - } - if (_parameters.size() != other._parameters.size()) { - return false; - } - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (*_parameters[i] != *other._parameters[i]) { - return false; - } - } - return true; -} - -/** - * - */ -bool CPPParameterList:: -operator != (const CPPParameterList &other) const { - return !(*this == other); -} - -/** - * - */ -bool CPPParameterList:: -operator < (const CPPParameterList &other) const { - if (_includes_ellipsis != other._includes_ellipsis) { - return _includes_ellipsis < other._includes_ellipsis; - } - if (_parameters.size() != other._parameters.size()) { - return _parameters.size() < other._parameters.size(); - } - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (*_parameters[i] != *other._parameters[i]) { - return *_parameters[i] < *other._parameters[i]; - } - } - return false; -} - -/** - * Returns true if any of the types in the parameter list are base on - * CPPTBDType. - */ -bool CPPParameterList:: -is_tbd() const { - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (_parameters[i]->_type->is_tbd()) { - return true; - } - } - return false; -} - -/** - * Returns true if any of the types in the parameter list turns out to be a - * constant expression, which is a clue that this parameter list is actually - * intended to be an instance declaration. - */ -bool CPPParameterList:: -is_parameter_expr() const { - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (_parameters[i]->_type->is_parameter_expr()) { - return true; - } - } - return false; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPParameterList:: -is_fully_specified() const { - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (!_parameters[i]->is_fully_specified()) { - return false; - } - } - - return true; -} - -/** - * - */ -CPPParameterList *CPPParameterList:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPParameterList *rep = new CPPParameterList; - bool any_changed = false; - for (int i = 0; i < (int)_parameters.size(); ++i) { - CPPInstance *inst = - _parameters[i]->substitute_decl(subst, current_scope, global_scope) - ->as_instance(); - if (inst != _parameters[i]) { - any_changed = true; - } - rep->_parameters.push_back(inst); - } - - if (!any_changed) { - delete rep; - rep = this; - } - return rep; -} - - -/** - * Returns an equivalent CPPParameterList, in which all of the individual - * types have been resolved. - */ -CPPParameterList *CPPParameterList:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPParameterList *rep = new CPPParameterList; - bool any_changed = false; - for (int i = 0; i < (int)_parameters.size(); ++i) { - CPPInstance *inst = _parameters[i]; - CPPType *new_type = inst->_type; - if (new_type->is_tbd()) { - new_type = new_type->resolve_type(current_scope, global_scope); - } - - if (new_type != inst->_type) { - any_changed = true; - CPPInstance *new_inst = new CPPInstance(*inst); - new_inst->_type = new_type; - rep->_parameters.push_back(new_inst); - } else { - rep->_parameters.push_back(inst); - } - } - - if (!any_changed) { - delete rep; - rep = this; - } - return rep; -} - -/** - * If num_default_parameters is >= 0, it indicates the number of default - * parameter values to show on output. Otherwise, all parameter values are - * shown. - */ -void CPPParameterList:: -output(std::ostream &out, CPPScope *scope, bool parameter_names, - int num_default_parameters) const { - if (!_parameters.empty()) { - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (i != 0) { - out << ", "; - } - - // Save the default value expression; we might be about to temporarily - // clear it. - CPPExpression *expr = _parameters[i]->_initializer; - - if (num_default_parameters >= 0 && - i < (int)_parameters.size() - num_default_parameters) { - // Don't show the default value for this parameter. - _parameters[i]->_initializer = nullptr; - } - - if (parameter_names) { - _parameters[i]->output(out, 0, scope, false); - } else { - _parameters[i]->_type->output(out, 0, scope, false); - } - - // Restore the default value expression. - _parameters[i]->_initializer = expr; - } - if (_includes_ellipsis) { - out << ", ..."; - } - - } else if (_includes_ellipsis) { - out << "..."; - - } else { - // No parameters. - out << "void"; - } -} diff --git a/dtool/src/cppparser/cppParameterList.h b/dtool/src/cppparser/cppParameterList.h deleted file mode 100644 index a5e5d327e9..0000000000 --- a/dtool/src/cppparser/cppParameterList.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppParameterList.h - * @author drose - * @date 1999-10-21 - */ - -#ifndef CPPPARAMETERLIST_H -#define CPPPARAMETERLIST_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -#include - -class CPPInstance; -class CPPScope; - -/** - * A list of formal parameters for a function declaration. - */ -class CPPParameterList { -public: - CPPParameterList(); - - bool is_equivalent(const CPPParameterList &other) const; - - bool operator == (const CPPParameterList &other) const; - bool operator != (const CPPParameterList &other) const; - bool operator < (const CPPParameterList &other) const; - - bool is_tbd() const; - bool is_parameter_expr() const; - - bool is_fully_specified() const; - CPPParameterList *substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - CPPParameterList *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - // This vector contains a list of formal parameters, in order. A parameter - // may have an empty identifer name. - typedef std::vector Parameters; - Parameters _parameters; - bool _includes_ellipsis; - - void output(std::ostream &out, CPPScope *scope, bool parameter_names, - int num_default_parameters = -1) const; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPParameterList &plist) { - plist.output(out, nullptr, true); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppParser.cxx b/dtool/src/cppparser/cppParser.cxx deleted file mode 100644 index f236a238c9..0000000000 --- a/dtool/src/cppparser/cppParser.cxx +++ /dev/null @@ -1,93 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppParser.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppParser.h" -#include "cppFile.h" -#include "cppTypeParser.h" -#include "cppBisonDefs.h" - -#include -#include - -bool cppparser_output_class_keyword = false; - -/** - * - */ -CPPParser:: -CPPParser() : CPPScope(nullptr, CPPNameComponent(""), V_public) { -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPParser:: -is_fully_specified() const { - // The global scope is always considered to be "fully specified", even if it - // contains some template declarations. - return true; -} - -/** - * - */ -bool CPPParser:: -parse_file(const Filename &filename) { - Filename canonical(filename); - canonical.make_canonical(); - - CPPFile file(canonical, filename, CPPFile::S_local); - - // Don't read it if we included it before and it had #pragma once. - ParsedFiles::iterator it = _parsed_files.find(file); - if (it != _parsed_files.end() && it->_pragma_once) { - // But mark it as local. - it->_source = CPPFile::S_local; - return true; - } - - if (!init_cpp(file)) { - std::cerr << "Unable to read " << filename << "\n"; - return false; - } - parse_cpp(this); - - return get_error_count() == 0; -} - -/** - * Given a string, expand all manifests within the string and evaluate it as - * an expression. Returns NULL if the string is not a valid expression. - */ -CPPExpression *CPPParser:: -parse_expr(const std::string &expr) { - YYLTYPE loc = {}; - return CPPPreprocessor::parse_expr(expr, this, this, loc); -} - -/** - * Given a string, interpret it as a type name and return the corresponding - * CPPType. Returns NULL if the string is not a valid type. - */ -CPPType *CPPParser:: -parse_type(const std::string &type) { - CPPTypeParser ep(this, this); - ep._verbose = 0; - if (ep.parse_type(type, *this)) { - return ep._type; - } else { - return nullptr; - } -} diff --git a/dtool/src/cppparser/cppParser.h b/dtool/src/cppparser/cppParser.h deleted file mode 100644 index 82ac2abd08..0000000000 --- a/dtool/src/cppparser/cppParser.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppParser.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPPARSER_H -#define CPPPARSER_H - -#include "dtoolbase.h" - -#include "cppScope.h" -#include "cppPreprocessor.h" -#include "filename.h" - -#include - -/** - * - */ -class CPPParser : public CPPScope, public CPPPreprocessor { -public: - CPPParser(); - - virtual bool is_fully_specified() const; - - bool parse_file(const Filename &filename); - - CPPExpression *parse_expr(const std::string &expr); - CPPType *parse_type(const std::string &type); -}; - -/* - * Normally, this variable should be left true, especially while parsing. - * However, after parsing has finished, and you want to output the results of - * parsing in a way that can be successfully compiled by VC++, you may need to - * set this variable to false. It controls the way typenames are written. - * When true, class names are written 'class X', which is the way the parser - * expects things to come, and which compiles successfully under every - * compiler except VC++. When false, class names are written simply 'X', - * which is the only way they'll compile under VC++. - */ -extern bool cppparser_output_class_keyword; - -#endif diff --git a/dtool/src/cppparser/cppPointerType.cxx b/dtool/src/cppparser/cppPointerType.cxx deleted file mode 100644 index 768bd43841..0000000000 --- a/dtool/src/cppparser/cppPointerType.cxx +++ /dev/null @@ -1,308 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppPointerType.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppPointerType.h" -#include "cppFunctionType.h" -#include "cppIdentifier.h" -#include "cppArrayType.h" -#include "cppStructType.h" -#include "cppSimpleType.h" - -/** - * - */ -CPPPointerType:: -CPPPointerType(CPPType *pointing_at) : - CPPType(CPPFile()), - _pointing_at(pointing_at) -{ -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPPointerType:: -is_fully_specified() const { - return CPPType::is_fully_specified() && - _pointing_at->is_fully_specified(); -} - -/** - * - */ -CPPDeclaration *CPPPointerType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPPointerType *rep = new CPPPointerType(*this); - rep->_pointing_at = - _pointing_at->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - - if (rep->_pointing_at == _pointing_at) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_pointer_type(); - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPPointerType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *ptype = _pointing_at->resolve_type(current_scope, global_scope); - - if (ptype != _pointing_at) { - CPPPointerType *rep = new CPPPointerType(*this); - rep->_pointing_at = ptype; - return CPPType::new_type(rep); - } - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPPointerType:: -is_tbd() const { - return _pointing_at->is_tbd(); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPPointerType:: -is_standard_layout() const { - return true; -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPPointerType:: -is_trivial() const { - return true; -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPPointerType:: -is_trivially_copyable() const { - return true; -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPPointerType:: -is_constructible(const CPPType *given_type) const { - given_type = ((CPPType *)given_type)->remove_reference()->remove_cv(); - - // Can convert from compatible pointer or array type. - CPPType *other_target; - switch (given_type->get_subtype()) { - case ST_array: - other_target = given_type->as_array_type()->_element_type; - break; - - case ST_pointer: - other_target = given_type->as_pointer_type()->_pointing_at; - break; - - case ST_simple: - // Can initialize from nullptr. - return given_type->as_simple_type()->_type == CPPSimpleType::T_nullptr; - - default: - return false; - } - - // Can't convert const to non-const pointer. - if (other_target->is_const() && !_pointing_at->is_const()) { - return false; - } - - // Are we pointing to the same type? That's always OK. - const CPPType *a = _pointing_at->remove_cv(); - const CPPType *b = other_target->remove_cv(); - if (a == b || *a == *b) { - return true; - } - - // Can initialize void pointer with any pointer. - const CPPSimpleType *simple_type = a->as_simple_type(); - if (simple_type != nullptr) { - return simple_type->_type == CPPSimpleType::T_void; - } - - // Can initialize from derived class pointer. - const CPPStructType *a_struct = a->as_struct_type(); - const CPPStructType *b_struct = b->as_struct_type(); - if (a_struct != nullptr && b_struct != nullptr) { - return a_struct->is_base_of(b_struct); - } - - return false; -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPPointerType:: -is_default_constructible() const { - return true; -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPPointerType:: -is_copy_constructible() const { - return true; -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPPointerType:: -is_copy_assignable() const { - return true; -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPPointerType:: -is_equivalent(const CPPType &other) const { - const CPPPointerType *ot = ((CPPType *)&other)->as_pointer_type(); - if (ot == nullptr) { - return CPPType::is_equivalent(other); - } - - return _pointing_at->is_equivalent(*ot->_pointing_at); -} - -/** - * - */ -void CPPPointerType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - /* - CPPFunctionType *ftype = _pointing_at->as_function_type(); - if (ftype != (CPPFunctionType *)NULL) { - // Pointers to functions are a bit of a special case; we have to be a - // little more careful about where the '*' goes. - - string star = "*"; - if ((ftype->_flags & CPPFunctionType::F_method_pointer) != 0) { - // We have to output pointers-to-method with a scoping before the '*'. - star = ftype->_class_owner->get_fully_scoped_name() + "::*"; - } - - _pointing_at->output_instance(out, indent_level, scope, complete, - star, ""); - - } else { - _pointing_at->output(out, indent_level, scope, complete); - out << " *"; - } - */ - output_instance(out, indent_level, scope, complete, "", ""); -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPPointerType:: -output_instance(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const { - std::string star = "*"; - - CPPFunctionType *ftype = _pointing_at->as_function_type(); - if (ftype != nullptr && - ((ftype->_flags & CPPFunctionType::F_method_pointer) != 0)) { - // We have to output pointers-to-method with a scoping before the '*'. - star = ftype->_class_owner->get_fully_scoped_name() + "::*"; - } - - if (!_attributes.is_empty()) { - std::ostringstream strm; - strm << star << _attributes << " "; - star = strm.str(); - } - - _pointing_at->output_instance(out, indent_level, scope, complete, - star + prename, name); -} - -/** - * - */ -CPPDeclaration::SubType CPPPointerType:: -get_subtype() const { - return ST_pointer; -} - -/** - * - */ -CPPPointerType *CPPPointerType:: -as_pointer_type() { - return this; -} - - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPPointerType:: -is_equal(const CPPDeclaration *other) const { - const CPPPointerType *ot = ((CPPDeclaration *)other)->as_pointer_type(); - assert(ot != nullptr); - - return _pointing_at == ot->_pointing_at; -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPPointerType:: -is_less(const CPPDeclaration *other) const { - const CPPPointerType *ot = ((CPPDeclaration *)other)->as_pointer_type(); - assert(ot != nullptr); - - return _pointing_at < ot->_pointing_at; -} diff --git a/dtool/src/cppparser/cppPointerType.h b/dtool/src/cppparser/cppPointerType.h deleted file mode 100644 index 683398be73..0000000000 --- a/dtool/src/cppparser/cppPointerType.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppPointerType.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPPOINTERTYPE_H -#define CPPPOINTERTYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -/** - * - */ -class CPPPointerType : public CPPType { -public: - CPPPointerType(CPPType *pointing_at); - - CPPType *_pointing_at; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *other) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - virtual bool is_equivalent(const CPPType &other) const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - - virtual SubType get_subtype() const; - - virtual CPPPointerType *as_pointer_type(); - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx deleted file mode 100644 index 74d2803e5c..0000000000 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ /dev/null @@ -1,3305 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppPreprocessor.cxx - * @author drose - * @date 1999-10-22 - */ - -#include "cppPreprocessor.h" -#include "cppExpressionParser.h" -#include "cppExpression.h" -#include "cppScope.h" -#include "cppIdentifier.h" -#include "cppTemplateScope.h" -#include "cppTemplateParameterList.h" -#include "cppClassTemplateParameter.h" -#include "cppConstType.h" -#include "cppFunctionGroup.h" -#include "cppFunctionType.h" -#include "cppPointerType.h" -#include "cppParameterList.h" -#include "cppSimpleType.h" -#include "cppGlobals.h" -#include "cppCommentBlock.h" -#include "cppBison.h" -#include "indent.h" -#include "pstrtod.h" -#include "string_utils.h" - -#include -#include -#include - -using std::cerr; -using std::string; - -// We manage our own visibility counter, in addition to that managed by -// cppBison.y. We do this just so we can define manifests with the correct -// visibility when they are declared. (Asking the parser for the current -// visibility is prone to error, since the parser might be several tokens -// behind the preprocessor.) -static CPPVisibility preprocessor_vis = V_public; - -// Don't forget to update CPPToken::output() when adding entries. -static const std::unordered_map keywords = { - {"alignas", KW_ALIGNAS}, - {"alignof", KW_ALIGNOF}, - {"__alignof", KW_ALIGNOF}, - {"__alignof__", KW_ALIGNOF}, - {"auto", KW_AUTO}, - {"__begin_publish", KW_BEGIN_PUBLISH}, - {"__blocking", KW_BLOCKING}, - {"bool", KW_BOOL}, - {"__builtin_va_list", KW_BUILTIN_VA_LIST}, - {"catch", KW_CATCH}, - {"char", KW_CHAR}, - {"char8_t", KW_CHAR8_T}, - {"char16_t", KW_CHAR16_T}, - {"char32_t", KW_CHAR32_T}, - {"class", KW_CLASS}, - {"const", KW_CONST}, - {"__const", KW_CONST}, - {"__const__", KW_CONST}, - {"consteval", KW_CONSTEVAL}, - {"constexpr", KW_CONSTEXPR}, - {"constinit", KW_CONSTINIT}, - {"const_cast", KW_CONST_CAST}, - {"decltype", KW_DECLTYPE}, - {"default", KW_DEFAULT}, - {"delete", KW_DELETE}, - {"double", KW_DOUBLE}, - {"dynamic_cast", KW_DYNAMIC_CAST}, - {"else", KW_ELSE}, - {"__end_publish", KW_END_PUBLISH}, - {"enum", KW_ENUM}, - {"extern", KW_EXTERN}, - {"__extension", KW_EXTENSION}, - {"explicit", KW_EXPLICIT}, - {"__published", KW_PUBLISHED}, - {"false", KW_FALSE}, - {"final", KW_FINAL}, - {"float", KW_FLOAT}, - {"friend", KW_FRIEND}, - {"for", KW_FOR}, - {"goto", KW_GOTO}, - {"__has_virtual_destructor", KW_HAS_VIRTUAL_DESTRUCTOR}, - {"if", KW_IF}, - {"inline", KW_INLINE}, - {"__inline", KW_INLINE}, - {"__inline__", KW_INLINE}, - {"int", KW_INT}, - {"__is_abstract", KW_IS_ABSTRACT}, - {"__is_base_of", KW_IS_BASE_OF}, - {"__is_class", KW_IS_CLASS}, - {"__is_constructible", KW_IS_CONSTRUCTIBLE}, - {"__is_convertible_to", KW_IS_CONVERTIBLE_TO}, - {"__is_destructible", KW_IS_DESTRUCTIBLE}, - {"__is_empty", KW_IS_EMPTY}, - {"__is_enum", KW_IS_ENUM}, - {"__is_final", KW_IS_FINAL}, - {"__is_fundamental", KW_IS_FUNDAMENTAL}, - {"__is_pod", KW_IS_POD}, - {"__is_polymorphic", KW_IS_POLYMORPHIC}, - {"__is_standard_layout", KW_IS_STANDARD_LAYOUT}, - {"__is_trivial", KW_IS_TRIVIAL}, - {"__is_trivially_copyable", KW_IS_TRIVIALLY_COPYABLE}, - {"__is_union", KW_IS_UNION}, - {"long", KW_LONG}, - {"__make_map_keys_seq", KW_MAKE_MAP_KEYS_SEQ}, - {"__make_map_property", KW_MAKE_MAP_PROPERTY}, - {"__make_property", KW_MAKE_PROPERTY}, - {"__make_property2", KW_MAKE_PROPERTY2}, - {"__make_seq", KW_MAKE_SEQ}, - {"__make_seq_property", KW_MAKE_SEQ_PROPERTY}, - {"mutable", KW_MUTABLE}, - {"namespace", KW_NAMESPACE}, - {"noexcept", KW_NOEXCEPT}, - {"nullptr", KW_NULLPTR}, - {"new", KW_NEW}, - {"operator", KW_OPERATOR}, - {"override", KW_OVERRIDE}, - {"private", KW_PRIVATE}, - {"protected", KW_PROTECTED}, - {"public", KW_PUBLIC}, - {"register", KW_REGISTER}, - {"reinterpret_cast", KW_REINTERPRET_CAST}, - //{"restrict", KW_RESTRICT}, - {"__restrict", KW_RESTRICT}, - {"__restrict__", KW_RESTRICT}, - {"return", KW_RETURN}, - {"short", KW_SHORT}, - {"signed", KW_SIGNED}, - {"sizeof", KW_SIZEOF}, - {"static", KW_STATIC}, - {"static_assert", KW_STATIC_ASSERT}, - {"static_cast", KW_STATIC_CAST}, - {"struct", KW_STRUCT}, - {"template", KW_TEMPLATE}, - {"thread_local", KW_THREAD_LOCAL}, - {"throw", KW_THROW}, - {"true", KW_TRUE}, - {"try", KW_TRY}, - {"typedef", KW_TYPEDEF}, - {"typeid", KW_TYPEID}, - {"typename", KW_TYPENAME}, - {"__underlying_type", KW_UNDERLYING_TYPE}, - {"union", KW_UNION}, - {"unsigned", KW_UNSIGNED}, - {"using", KW_USING}, - {"virtual", KW_VIRTUAL}, - {"void", KW_VOID}, - {"volatile", KW_VOLATILE}, - {"wchar_t", KW_WCHAR_T}, - {"while", KW_WHILE}, - - // These are alternative ways to refer to built-in operators. - {"and", ANDAND}, - {"and_eq", ANDEQUAL}, - {"bitand", '&'}, - {"bitor", '|'}, - {"compl", '~'}, - {"not", '!'}, - {"not_eq", NECOMPARE}, - {"or", OROR}, - {"or_eq", OREQUAL}, - {"xor", '^'}, - {"xor_eq", XOREQUAL}, -}; - -static int -hex_val(int c) { - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return (c - '0'); - - default: - return (tolower(c) - 'a' + 10); - } -} - -static string -trim_blanks(const string &str) { - size_t first, last; - - if(str.empty()) - return str; - - first = 0; - while (first < str.length() && isspace(str[first])) { - first++; - } - - last = str.length() - 1; - while (last > first && isspace(str[last])) { - last--; - } - - return str.substr(first, last - first + 1); -} - -/** - * - */ -CPPPreprocessor::InputFile:: -InputFile() { - _in = nullptr; - _manifest = nullptr; - _line_number = 0; - _col_number = 0; - _next_line_number = 1; - _next_col_number = 1; - _lock_position = false; - _ignore_manifest = false; -} - -/** - * - */ -CPPPreprocessor::InputFile:: -~InputFile() { - if (_in != nullptr) { - // For some reason--compiler bug in gcc 3.2?--explicitly deleting the - // stream pointer does not call the appropriate global delete function; - // instead apparently calling the system delete function. So we call the - // delete function by hand instead. -#if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) - _in->~istream(); - (*global_operator_delete)(_in); -#else - delete _in; -#endif - } -} - -/** - * - */ -bool CPPPreprocessor::InputFile:: -open(const CPPFile &file) { - assert(_in == nullptr); - - _file = file; - pifstream *in = new pifstream; - _in = in; - - return _file._filename.open_read(*in); -} - -/** - * - */ -bool CPPPreprocessor::InputFile:: -connect_input(const string &input) { - assert(_in == nullptr); - - _input = input; - _in = new std::istringstream(_input); - return !_in->fail(); -} - -/** - * Fetches a single character from the source file. - */ -int CPPPreprocessor::InputFile:: -get() { - assert(_in != nullptr); - - if (!_lock_position) { - _line_number = _next_line_number; - _col_number = _next_col_number; - } - - int c = _in->get(); - - // Quietly skip over embedded carriage-return characters. We shouldn't see - // any of these unless there was some DOS-to-Unix file conversion problem. - while (c == '\r') { - c = _in->get(); - } - - switch (c) { - case EOF: - break; - - case '\n': - if (!_lock_position) { - ++_next_line_number; - _next_col_number = 1; - } - break; - - default: - if (!_lock_position) { - ++_next_col_number; - } - } - - return c; -} - -/** - * Like get(), but does not advance the file pointer. - */ -int CPPPreprocessor::InputFile:: -peek() { - assert(_in != nullptr); - - int c = _in->peek(); - - // Quietly skip over embedded carriage-return characters. We shouldn't see - // any of these unless there was some DOS-to-Unix file conversion problem. - while (c == '\r') { - _in->get(); - c = _in->peek(); - } - - return c; -} - -/** - * - */ -CPPPreprocessor:: -CPPPreprocessor() { - _noangles = false; - _state = S_eof; - _paren_nesting = 0; - _parsing_template_params = false; - _parsing_attribute = false; - _unget = '\0'; - _last_c = '\0'; - _start_of_line = true; - _last_cpp_comment = false; - _save_comments = true; - - _resolve_identifiers = true; - - _warning_count = 0; - _error_count = 0; - _error_abort = false; -#ifdef CPP_VERBOSE_LEX - _token_index = 0; -#endif - _verbose = 1; -} - -/** - * - */ -bool CPPPreprocessor:: -preprocess_file(const Filename &filename) { - Filename canonical(filename); - canonical.make_canonical(); - - CPPFile file(canonical, filename, CPPFile::S_local); - - // Don't read it if we included it before and it had #pragma once. - ParsedFiles::iterator it = _parsed_files.find(file); - if (it != _parsed_files.end() && it->_pragma_once) { - // But mark it as local. - it->_source = CPPFile::S_local; - return true; - } - - if (!init_cpp(file)) { - std::cerr << "Unable to read " << filename << "\n"; - return false; - } - - int line_number = 1; - int nesting = 0; - bool next_space = false; - CPPToken token = get_next_token(); - while (!token.is_eof()) { - if (token._token == '}') { - nesting -= 1; - } - if (token._lloc.first_line > line_number) { - // Token is on a different line, so insert a newline. - std::cout << "\n"; - line_number = token._lloc.first_line; - indent(std::cout, nesting * 2); - } - else if (next_space && token._token != ';' && token._token != ':' && token._token != ',' && token._token != ')') { - // The above tokens never need a preceding space - std::cout << " "; - } - if (token._token == '{') { - nesting += 1; - } - next_space = (token._token != '(' && token._token != '~'); - token.output_code(std::cout); - - CPPToken next_token = get_next_token(); - if (next_token._lloc.file != token._lloc.file) { - // Switched to a new file, reset the line number. - line_number = 0; - } - token = std::move(next_token); - } - std::cout << "\n"; - - return get_error_count() == 0; -} - -/** - * Sets the verbosity level of the parser. At 0, no warnings will be - * reported; at 1 or higher, expect to get spammed. - */ -void CPPPreprocessor:: -set_verbose(int verbose) { - _verbose = verbose; -} - -/** - * Returns the verbosity level of the parser. - */ -int CPPPreprocessor:: -get_verbose() const { - return _verbose; -} - -/** - * - */ -void CPPPreprocessor:: -copy_filepos(const CPPPreprocessor &other) { - InputFile *infile = _infile; - assert(infile != nullptr); - infile->_file = other.get_file(); - infile->_line_number = other.get_line_number(); - infile->_col_number = other.get_col_number(); -} - -/** - * - */ -CPPFile CPPPreprocessor:: -get_file() const { - InputFile *infile = _infile; - if (infile != nullptr) { - return infile->_file; - } else { - return CPPFile(""); - } -} - -/** - * Returns the line number of the last character returned by get(). - */ -int CPPPreprocessor:: -get_line_number() const { - InputFile *infile = _infile; - if (infile != nullptr) { - return infile->_line_number; - } else { - return 0; - } -} - -/** - * Returns the column number of the last character returned by get(). - */ -int CPPPreprocessor:: -get_col_number() const { - InputFile *infile = _infile; - if (infile != nullptr) { - return infile->_col_number; - } else { - return 0; - } -} - -/** - * - */ -CPPToken CPPPreprocessor:: -get_next_token() { - -#ifdef CPP_VERBOSE_LEX - CPPToken tok = get_next_token0(); - indent(cerr, get_file_depth() * 2) - << _token_index++ << ". " << tok << "\n"; - return tok; -} - -CPPToken CPPPreprocessor:: -get_next_token0() { -#endif - - // We make a nested call to internal_get_next_token(), so we can combine - // sequences of identifiers and scoping symbols into a single identifier, - // for yacc's convenience. - - CPPToken token(0); - if (!_saved_tokens.empty()) { - token = std::move(_saved_tokens.back()); - _saved_tokens.pop_back(); - } else { - token = internal_get_next_token(); - } - - YYLTYPE loc = token._lloc; - - if (_resolve_identifiers && - (token._token == SIMPLE_IDENTIFIER || token._token == SCOPE)) { - // We will be returning a scoped identifier, or a scoping. Keep pulling - // off tokens until we reach the end of the scopeidentifier sequence. - - string name; - - // If we started the ball with an identifier, use it and get the next - // token. Otherwise, we started with :: (global scope), and we indicate - // this with an empty string at the beginning of the scoping sequence. - if (token._token == SIMPLE_IDENTIFIER) { - name = token._lval.str; - token = internal_get_next_token(); - } - - CPPIdentifier *ident = new CPPIdentifier(name, loc); - YYSTYPE result; - result.u.identifier = ident; - - if (token._token == '<') { - // If the next token is an angle bracket and the current identifier - // wants template instantiation, assume the angle bracket begins the - // instantiation and call yacc recursively to parse the template - // parameters. - CPPDeclaration *decl = ident->find_template(current_scope, global_scope); - if (decl != nullptr) { - ident->_names.back().set_templ - (nested_parse_template_instantiation(decl->get_template_scope())); - token = internal_get_next_token(); - //} else { - // error(string("unknown template '") + ident->get_fully_scoped_name() + "'", loc); - } - } - - while (token._token == SCOPE) { - loc.last_line = token._lloc.last_line; - loc.last_column = token._lloc.last_column; - - name += "::"; - token = internal_get_next_token(); - string token_prefix; - - if (token._token == '~') { - // A scoping operator followed by a tilde can only be the start of a - // scoped destructor name. Make the tilde be part of the name. - name += "~"; - token_prefix = "~"; - token = internal_get_next_token(); - } - - if (token._token != SIMPLE_IDENTIFIER) { - // The last useful token was a SCOPE, thus this is a scoping token. - - if (token._token == KW_OPERATOR) { - // Unless the last token we came across was the "operator" keyword. - // We make a special case for this, because it's occasionally scoped - // in normal use. - token._lval = result; - _last_token_loc = token._lloc; - return token; - } - _saved_tokens.push_back(token); - _last_token_loc = loc; - return CPPToken(SCOPING, loc, name, result); - } - - name += token._lval.str; - ident->_names.push_back(token_prefix + token._lval.str); - - loc.last_line = token._lloc.last_line; - loc.last_column = token._lloc.last_column; - ident->_loc.last_line = loc.last_line; - ident->_loc.last_column = loc.last_column; - - token = internal_get_next_token(); - - if (token._token == '<') { - // If the next token is an angle bracket and the current indentifier - // wants template instantiation, assume the angle bracket begins the - // instantiation and call yacc recursively to parse the template - // parameters. - CPPDeclaration *decl = - ident->find_template(current_scope, global_scope); - if (decl != nullptr) { - ident->_names.back().set_templ - (nested_parse_template_instantiation(decl->get_template_scope())); - token = internal_get_next_token(); - } else { - error(string("unknown template '") + ident->get_fully_scoped_name() + "'", loc); - } - } - } - // The last useful token was a SIMPLE_IDENTIFIER, thus this is a normal - // scoped identifier. - _saved_tokens.push_back(token); - - int token_type = IDENTIFIER; - CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope); - if (decl != nullptr && decl->as_type() != nullptr) { - // We need to see type pack template parameters as a different type of - // identifier to resolve a parser ambiguity. - CPPClassTemplateParameter *ctp = decl->as_class_template_parameter(); - if (ctp && ctp->_packed) { - token_type = TYPEPACK_IDENTIFIER; - } else { - token_type = TYPENAME_IDENTIFIER; - } - } - - _last_token_loc = loc; - return CPPToken(token_type, loc, name, result); - } - - // This is the normal case: just pass through whatever token we got. - _last_token_loc = loc; - return token; -} - -/** - * - */ -CPPToken CPPPreprocessor:: -peek_next_token() { - CPPToken token(0); - if (!_saved_tokens.empty()) { - token = _saved_tokens.back(); - } else { - token = internal_get_next_token(); - _saved_tokens.push_back(token); - } - return token; -} - -/** - * - */ -void CPPPreprocessor:: -warning(const string &message) const { - if (_verbose < 2) { - return; - } - int line = get_line_number(); - int col = get_col_number(); - YYLTYPE loc; - loc.first_line = line; - loc.first_column = col; - loc.last_line = line; - loc.last_column = col; - loc.file = get_file(); - warning(message, loc); -} - -/** - * - */ -void CPPPreprocessor:: -warning(const string &message, const YYLTYPE &loc) const { - if (_verbose >= 2) { - if (_verbose >= 3) { - indent(cerr, get_file_depth() * 2); - } - - if (!loc.file.empty()) { - cerr << loc.file << ':'; - } - if (loc.first_line) { - cerr << loc.first_line << ':'; - - if (loc.first_column) { - cerr << loc.first_column << ':'; - } - } - - cerr << " warning: " << message << "\n"; - show_line(loc); - } - _warning_count++; -} - -/** - * - */ -void CPPPreprocessor:: -error(const string &message) const { - int line = get_line_number(); - int col = get_col_number(); - YYLTYPE loc; - loc.first_line = line; - loc.first_column = col; - loc.last_line = line; - loc.last_column = col; - loc.file = get_file(); - error(message, loc); -} - -/** - * - */ -void CPPPreprocessor:: -error(const string &message, const YYLTYPE &loc) const { - if (_state == S_nested || _state == S_end_nested) { - // Don't report or log errors in the nested state. These will be reported - // when the nesting level collapses. - return; - } - - if (_verbose >= 1) { - if (_verbose >= 3) { - indent(cerr, get_file_depth() * 2); - } - - if (!loc.file.empty()) { - cerr << loc.file << ':'; - } - if (loc.first_line) { - cerr << loc.first_line << ':'; - - if (loc.first_column) { - cerr << loc.first_column << ':'; - } - } - - cerr << " error: " << message << "\n"; - show_line(loc); - - InputFile *infile = _infile; - if (infile != nullptr && !loc.file.empty()) { - // Add all the expansions to a vector for easy reverse iteration. - std::vector infiles; - while (infile != nullptr && infile->_file == loc.file && infile->_manifest != nullptr) { - infiles.push_back(infile); - infile = infile->_parent; - } - if (!infiles.empty()) { - auto rit = infiles.rbegin(); - if (_verbose >= 3) { - cerr << "Expansion of " << (*rit)->_manifest->_name << ":\n"; - while (rit != infiles.rend()) { - cerr << " -> " << trim_blanks((*rit)->_input) << "\n"; - ++rit; - } - } - else { - cerr << "with " << (*rit)->_manifest->_name; - if ((*rit)->_manifest->_has_parameters) { - cerr << "()"; - } - cerr << " expanded to: " << trim_blanks(_infile->_input) << "\n"; - } - cerr << std::endl; - } - } - - if (_error_abort) { - cerr << "Aborting.\n"; - abort(); - } - } - _error_count++; -} - -/** - * Shows the indicated line, useful for error messages. - */ -void CPPPreprocessor:: -show_line(const YYLTYPE &loc) const { - if (loc.file._filename.empty()) { - return; - } - - int indent_level = 0; - if (_verbose >= 3) { - indent_level = get_file_depth() * 2; - } - - // Seek to the offending line in the file. - std::ifstream stream; - if (loc.file._filename.open_read(stream)) { - int l = 0; - string linestr; - while (l < loc.first_line) { - std::getline(stream, linestr); - ++l; - } - - // Strip off trailing whitespace. - size_t last = linestr.length(); - while (isspace(linestr[--last])) { - linestr = linestr.substr(0, last); - } - - indent(cerr, indent_level) << linestr << "\n"; - - // Point the user at the offending column. - if (loc.first_column) { - int last_column; - if (loc.first_line == loc.last_line && loc.last_column) { - last_column = loc.last_column; - } else { - last_column = linestr.length(); - } - - indent(cerr, indent_level); - int i = 0; - for (; i < loc.first_column - 1; ++i) { - cerr.put(' '); - } - cerr.put('^'); - while (++i < last_column) { - cerr.put('~'); - } - cerr << "\n"; - } - } -} - -/** - * - */ -int CPPPreprocessor:: -get_warning_count() const { - return _warning_count; -} - -/** - * - */ -int CPPPreprocessor:: -get_error_count() const { - return _error_count; -} - -/** - * Returns the CPPCommentBlock immediately preceding the indicated line, if - * any. If there is no such comment, returns NULL. - */ -CPPCommentBlock *CPPPreprocessor:: -get_comment_before(int line, CPPFile file) { - CPPComments::reverse_iterator ci; - ci = _comments.rbegin(); - - int wrong_file_count = 0; - while (ci != _comments.rend()) { - CPPCommentBlock *comment = (*ci); - if (comment->_file == file) { - wrong_file_count = 0; - if (comment->_last_line == line || comment->_last_line == line - 1) { - return comment; - } - - if (comment->_last_line < line) { - return nullptr; - } - } else { - wrong_file_count++; - if (wrong_file_count > 10) { - return nullptr; - } - } - - ++ci; - } - - return nullptr; -} - -/** - * Returns the CPPCommentBlock that starts on the indicated line, if any. If - * there is no such comment, returns NULL. - */ -CPPCommentBlock *CPPPreprocessor:: -get_comment_on(int line, CPPFile file) { - CPPComments::reverse_iterator ci; - ci = _comments.rbegin(); - - while (ci != _comments.rend()) { - CPPCommentBlock *comment = (*ci); - if (comment->_file == file) { - if (comment->_line_number == line) { - return comment; - } else if (comment->_line_number < line) { - return nullptr; - } - } - - ++ci; - } - - return nullptr; -} - -/** - * - */ -bool CPPPreprocessor:: -init_cpp(const CPPFile &file) { - _state = S_normal; - _saved_tokens.push_back(CPPToken(START_CPP)); - _last_c = '\0'; - - return push_file(file); -} - -/** - * - */ -bool CPPPreprocessor:: -init_const_expr(const string &expr) { - _state = S_normal; - _saved_tokens.push_back(CPPToken(START_CONST_EXPR)); - - return push_string(expr); -} - -/** - * - */ -bool CPPPreprocessor:: -init_type(const string &type) { - _state = S_normal; - _saved_tokens.push_back(CPPToken(START_TYPE)); - - return push_string(type); -} - -/** - * - */ -bool CPPPreprocessor:: -push_file(const CPPFile &file) { - if (_verbose >= 3) { - indent(cerr, get_file_depth() * 2) - << "Reading " << file << "\n"; - } - assert(_last_c == 0); - - InputFile *infile = new InputFile; - if (infile->open(file)) { - infile->_parent = _infile; - _infile = infile; - - // Record the fact that we opened the file for the benefit of user code. - _parsed_files.insert(file); - - infile->_prev_last_c = _last_c; - _last_c = '\0'; - _start_of_line = true; - return true; - } - - delete infile; - return false; -} - -/** - * - */ -bool CPPPreprocessor:: -push_string(const string &input) { -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Pushing to string \"" << input - << "\"\n"; -#endif - - InputFile *infile = new InputFile; - if (infile->connect_input(input)) { - infile->_prev_last_c = _last_c; - infile->_parent = _infile; - _infile = infile; - _last_c = '\0'; - return true; - } - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Unable to read string\n"; -#endif - - delete infile; - return false; -} - -/** - * - */ -bool CPPPreprocessor:: -push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &loc) { -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Pushing to expansion \"" << input - << "\"\n"; -#endif - - InputFile *infile = new InputFile; - if (infile->connect_input(input)) { - infile->_manifest = manifest; - infile->_file = loc.file; - infile->_line_number = loc.first_line; - infile->_col_number = loc.first_column; - infile->_lock_position = true; - - if (!manifest->_has_parameters) { - // If the manifest does not use arguments, then disallow recursive - // expansion. - infile->_ignore_manifest = true; - } - - infile->_prev_last_c = _last_c; - infile->_parent = _infile; - _infile = infile; - _last_c = '\0'; - return true; - } - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Unable to read expansion\n"; -#endif - - delete infile; - return false; -} - -/** - * Given a string, expand all manifests within the string. - */ -void CPPPreprocessor:: -expand_manifests(string &expr, bool expand_undefined, - const CPPManifest::Ignores &ignores) const { - size_t p = 0; - while (p < expr.size()) { - if (isalpha(expr[p]) || expr[p] == '_') { - size_t q = p; - while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { - p++; - } - string ident = expr.substr(q, p - q); - - // Here's an identifier. Is it "defined"? - if (ident == "defined") { - expand_defined_function(expr, q, p); - } - else if (expand_undefined && ident == "__has_include") { - expand_has_include_function(expr, q, p); - } - else if (ident == "L" && p < expr.size() && (expr[p] == '\'' || expr[p] == '\"')) { - // Special exception for the wide string literal suffix, which is - // never expanded. - } - else { - // Is it a manifest? - Manifests::const_iterator mi = _manifests.find(ident); - if (mi != _manifests.end() && ignores.count((*mi).second) == 0) { - const CPPManifest *manifest = (*mi).second; - vector_string args; - if (manifest->_has_parameters) { - // If it's not followed by a parenthesis, don't expand it. - while (p < expr.size() && isspace(expr[p])) { - p++; - } - if (p >= expr.size() || expr[p] != '(') { - continue; - } - - manifest->extract_args(args, expr, p); - } - - // Don't consider this manifest when expanding the arguments or - // result, to prevent recursion. - CPPManifest::Ignores nested_ignores(ignores); - nested_ignores.insert(manifest); - - string result = manifest->expand(args, expand_undefined, nested_ignores); - expand_manifests(result, expand_undefined, nested_ignores); - - expr = expr.substr(0, q) + result + expr.substr(p); - p = q + result.size(); - } - else if (ident == "__FILE__") { - // Special case: this is a dynamic definition. - CPPFile file = get_file(); - string result = string("\"") + file._filename_as_referenced.get_fullpath() + "\""; - expr = expr.substr(0, q) + result + expr.substr(p); - p = q + result.size(); - - } - else if (ident == "__LINE__") { - // So is this. - string line = format_string(get_line_number()); - expr = expr.substr(0, q) + line + expr.substr(p); - p = q + line.size(); - } - else if (expand_undefined && ident != "true" && ident != "false") { - // It is not found. Expand it to 0, but only if we are currently - // parsing an #if expression. - expr = expr.substr(0, q) + "0" + expr.substr(p); - p = q + 1; - } - } - } - else if (expr[p] == '\'' || expr[p] == '"') { - // Skip the next part until we find a closing quotation mark. - char quote = expr[p]; - p++; - while (p < expr.size() && expr[p] != quote) { - if (expr[p] == '\\') { - // This might be an escaped quote. Skip an extra char. - p++; - } - p++; - } - if (p >= expr.size()) { - // Unclosed string. - warning("missing terminating " + string(1, quote) + " character"); - } - p++; - } - else { - p++; - } - } -} - -/** - * Given a string, expand all manifests within the string and evaluate it as - * an expression. Returns NULL if the string is not a valid expression. - * - * This is an internal support function for CPPPreprocessor; however, there is - * a public variant of this function defined for CPPParser. - */ -CPPExpression *CPPPreprocessor:: -parse_expr(const string &input_expr, CPPScope *current_scope, - CPPScope *global_scope, const YYLTYPE &loc) { - string expr = input_expr; - expand_manifests(expr, false); - - CPPExpressionParser ep(current_scope, global_scope); - ep._verbose = 0; - if (ep.parse_expr(expr, *this)) { - return ep._expr; - } else { - return nullptr; - } -} - -/** - * - */ -CPPToken CPPPreprocessor:: -internal_get_next_token() { - if (_state == S_eof || _state == S_end_nested) { - return CPPToken::eof(); - } - - int c = _last_c; - _last_c = '\0'; - if (c == '\0' || c == EOF) { - c = get(); - } - - // Skip any whitespace, comments, and preprocessor directives before the - // token. - c = skip_whitespace(c); - while (c == '#' && _start_of_line && !should_ignore_preprocessor()) { - c = skip_whitespace(process_directive(c)); - } - - if (c == '\'') { - return get_quoted_char(c); - } else if (c == '"') { - return get_quoted_string(c); - } else if (isalpha(c) || c == '_') { - return get_identifier(c); - } else if (isdigit(c)) { - return get_number(c); - } - - if (c == EOF) { - _state = S_eof; - return CPPToken::eof(); - } - - // Check for a number beginning with a decimal point. - int next_c = peek(); - if (c == '.' && isdigit(next_c)) { - return get_number(c); - } - - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - loc.last_line = loc.first_line; - loc.last_column = loc.first_column; - - // Check for two- or three-character tokens. - int di = check_digraph(c); - if (di != 0) { - c = di; - ++loc.last_column; - get(); - - int tri = check_trigraph(di); - if (tri != 0) { - ++loc.last_column; - get(); - return CPPToken(tri, loc); - } - return CPPToken(di, loc); - } - - if (_state == S_nested) { - // If we're running a nested lexer, keep track of the paren levels. When - // we encounter a comma or closing angle bracket at the bottom level, we - // stop. - - switch (c) { - case '(': - case '[': - _paren_nesting++; - break; - - case ')': - case ']': - _paren_nesting--; - break; - - case ',': - if (_paren_nesting <= 0) { - _state = S_end_nested; - return CPPToken(0, loc); - } - break; - - case '>': - if (_paren_nesting <= 0) { - _parsing_template_params = false; - _state = S_end_nested; - return CPPToken(0, loc); - } - } - } else if (_parsing_attribute) { - // If we're parsing an attribute, also keep track of the paren nesting. - if (c == '[' || c == '(') { - ++_paren_nesting; - } else if (c == ']' || c == ')') { - --_paren_nesting; - } - } - - // Look for an end-of-line comment, and parse it before we finish this - // token. This is not strictly necessary, but it allows us to pick up - // docstrings from comments after enum values. - while (next_c != EOF && isspace(next_c)) { - get(); - next_c = peek(); - } - if (next_c == '/') { - _last_c = skip_whitespace(get()); - } - - return CPPToken(c, loc); -} - -/** - * Checks the next character in the stream to see if this might be a two- - * character token. Returns 0 if it is only a single-character token. - */ -int CPPPreprocessor:: -check_digraph(int c) { - int next_c = peek(); - switch (c) { - case '+': - if (next_c == '+') return PLUSPLUS; - if (next_c == '=') return PLUSEQUAL; - break; - - case '-': - if (next_c == '-') return MINUSMINUS; - if (next_c == '=') return MINUSEQUAL; - if (next_c == '>') return POINTSAT; - break; - - case '<': - if (next_c == '<') return LSHIFT; - if (next_c == '=') return LECOMPARE; - if (next_c == ':') return '['; - if (next_c == '%') return '{'; - break; - - case '>': - if (_parsing_template_params && _paren_nesting <= 0) { - // Don't parse >> as right-shift when parsing a template list, as per - // C++11, to allow a syntax like A>. However, nested >> must be - // preserved, such as in A<(2>>1)> - break; - } - if (next_c == '>') return RSHIFT; - if (next_c == '=') return GECOMPARE; - break; - - case '|': - if (next_c == '|') return OROR; - if (next_c == '=') return OREQUAL; - break; - - case '&': - if (next_c == '&') return ANDAND; - if (next_c == '=') return ANDEQUAL; - break; - - case '^': - if (next_c == '=') return XOREQUAL; - break; - - case '=': - if (next_c == '=') return EQCOMPARE; - break; - - case '!': - if (next_c == '=') return NECOMPARE; - break; - - case '.': - if (next_c == '*') return DOT_STAR; - if (next_c == '.') { - get(); - if (peek() == '.') { - return ELLIPSIS; - } else { - unget('.'); - } - } - break; - - case ':': - if (next_c == ':') return SCOPE; - if (next_c == '>') return ']'; - break; - - case '*': - if (next_c == '=') return TIMESEQUAL; - break; - - case '/': - if (next_c == '=') return DIVIDEEQUAL; - break; - - case '%': - if (next_c == '=') return MODEQUAL; - if (next_c == '>') return '}'; - break; - - case '[': - if (next_c == '[' && !_parsing_attribute) { - _parsing_attribute = true; - return ATTR_LEFT; - } - break; - - case ']': - if (next_c == ']' && _parsing_attribute && _paren_nesting == 0) { - _parsing_attribute = false; - return ATTR_RIGHT; - } - break; - } - - return 0; -} - -/** - * Checks the next character in the stream to see if this might be a three- - * character token; usually called in conjunction with check_digraph. Returns - * 0 if it is not a three-character token. - */ -int CPPPreprocessor:: -check_trigraph(int c) { - int next_c = peek(); - switch (c) { - case POINTSAT: - if (next_c == '*') return POINTSAT_STAR; - break; - - case LSHIFT: - if (next_c == '=') return LSHIFTEQUAL; - break; - - case RSHIFT: - if (next_c == '=') return RSHIFTEQUAL; - break; - - case LECOMPARE: - if (next_c == '>') return SPACESHIP; - break; - } - - return 0; -} - -/** - * - */ -int CPPPreprocessor:: -skip_whitespace(int c) { - while (c != EOF) { - c = skip_comment(c); - - if (c == '\\') { - // This does not usually occur in the middle of unquoted C++ code, - // except before a newline character. - if (peek() != '\n') { - return '\\'; - } - c = get(); - } - - if (!isspace(c)) { - return c; - } - c = get(); - } - return c; -} - -/** - * - */ -int CPPPreprocessor:: -skip_comment(int c) { - while (c == '/') { - int next_c = peek(); - if (next_c == '*') { - get(); - _last_cpp_comment = false; - c = skip_c_comment(get()); - } else if (next_c == '/') { - get(); - c = skip_cpp_comment(get()); - break; - } else { - _last_cpp_comment = false; - return c; - } - } - if (!isspace(c)) { - _last_cpp_comment = false; - } - return c; -} - -/** - * - */ -int CPPPreprocessor:: -skip_c_comment(int c) { - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number() - 2; - loc.last_line = 0; - loc.last_column = 0; - - if (_save_comments) { - CPPCommentBlock *comment = new CPPCommentBlock; - _comments.push_back(comment); - - comment->_file = loc.file; - comment->_line_number = loc.first_line; - comment->_last_line = loc.last_line; - comment->_col_number = loc.first_column; - comment->_c_style = true; - comment->_comment = "/*"; - - while (c != EOF) { - if (c == '*') { - comment->_comment += c; - c = get(); - if (c == '/') { - comment->_comment += c; - comment->_last_line = get_line_number(); - return get(); - } - } else { - comment->_comment += c; - c = get(); - } - } - - loc.last_line = get_line_number(); - comment->_last_line = loc.last_line; - - warning("Comment is unterminated", loc); - - } else { - CPPFile first_file = get_file(); - - while (c != EOF) { - if (c == '*') { - c = get(); - if (c == '/') { - return get(); - } - } else { - c = get(); - } - } - - loc.last_line = get_line_number(); - - warning("Comment is unterminated", loc); - } - - return c; -} - -/** - * - */ -int CPPPreprocessor:: -skip_cpp_comment(int c) { - if (_save_comments) { - CPPCommentBlock *comment; - - int line_number = get_line_number(); - if (c == '\n') { - // We have to subtract one from the line number as we just fetched a - // newline. - --line_number; - } - - if (_last_cpp_comment && !_comments.empty() && - _comments.back()->_last_line >= line_number - 1) { - // If the last non-whitespace character read was also part of a C++ - // comment, then this is just a continuation of that comment block. - // However, if there was a line without comment in between, it starts a - // new block anyway. - comment = _comments.back(); - assert(!comment->_c_style); - comment->_comment += "//"; - - } else { - // Otherwise, this begins a new comment block. - comment = new CPPCommentBlock; - - comment->_file = get_file(); - comment->_line_number = line_number; - comment->_last_line = line_number; - comment->_col_number = get_col_number() - 2; - comment->_c_style = false; - comment->_comment = "//"; - - _comments.push_back(comment); - } - - while (c != EOF && c != '\n') { - comment->_comment += c; - c = get(); - } - - comment->_comment += '\n'; - comment->_last_line = line_number; - - _last_cpp_comment = true; - - } else { - while (c != EOF && c != '\n') { - c = get(); - } - } - - return c; -} - -/** - * Skips a C++14 digit separator that has just been found through peek(). - */ -int CPPPreprocessor:: -skip_digit_separator(int c) { - if (c != '\'') { - return c; - } - - get(); - c = peek(); - - if (isdigit(c)) { - return c; - } - - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - loc.last_line = loc.first_line; - loc.last_column = loc.first_column; - - if (c != '\'') { - // This assumes that this isn't a character constant directly follows a - // digit sequence, like 123'a' -- I can't think of a situation where - // that's legal anyway, though. - error("digit separator cannot occur at end of digit sequence", loc); - return c; - } - - while (c == '\'') { - get(); - ++loc.last_column; - c = peek(); - } - error("adjacent digit separators", loc); - - return c; -} - -/** - * - */ -int CPPPreprocessor:: -process_directive(int c) { - assert(c == '#'); - c = skip_whitespace(get()); - - int begin_line = get_line_number(); - int begin_column = get_col_number(); - - string command, args; - c = get_preprocessor_command(c, command); - - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - - c = get_preprocessor_args(c, args); - - loc.last_line = get_line_number(); - loc.last_column = 0; - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "#" << command << " " << args << "\n"; -#endif - - if (command == "define") { - handle_define_directive(args, loc); - } else if (command == "undef") { - handle_undef_directive(args, loc); - } else if (command == "ifdef") { - handle_ifdef_directive(args, loc); - } else if (command == "ifndef") { - handle_ifndef_directive(args, loc); - } else if (command == "if") { - handle_if_directive(args, loc); - } else if (command == "else" || command == "elif") { - // Presumably this follows some #if or #ifdef. We don't bother to check - // this, however. - skip_false_if_block(false); - } else if (command == "endif") { - // Presumably this follows some #if or #ifdef. We don't bother to check - // this, however. - } else if (command == "include") { - handle_include_directive(args, loc); - } else if (command == "pragma") { - handle_pragma_directive(args, loc); - } else if (command == "ident") { - // Quietly ignore idents. - } else if (command == "error") { - handle_error_directive(args, loc); - } else { - loc.first_line = begin_line; - loc.first_column = begin_column; - loc.last_line = begin_line; - loc.last_column = begin_column + command.size() - 1; - warning("Ignoring unknown directive #" + command, loc); - } - - _start_of_line = true; - return '\n'; -} - -/** - * - */ -int CPPPreprocessor:: -get_preprocessor_command(int c, string &command) { - // The next sequence of characters is the command. - while (c != EOF && (isalnum(c) || c == '_')) { - command += c; - c = get(); - } - - while (c != EOF && c != '\n' && isspace(c)) { - c = get(); - } - - return c; -} - -/** - * - */ -int CPPPreprocessor:: -get_preprocessor_args(int c, string &args) { - // Following the command, the rest of the line, as well as any text on - // successive lines, is part of the arguments to the command. - - // Check for comments first. - c = skip_comment(c); - - while (c != EOF && c != '\n') { - if (c == '\\') { - int next_c = get(); - if (next_c == '\n') { - // Here we have an escaped newline: a continuation. - args += '\n'; - } else { - // Just a backslash followed by some non-backslash, keep both. - args += c; - if (next_c != EOF) { - args += next_c; - } - } - } else { - args += c; - } - c = skip_comment(get()); - } - - // Remove any leading and trailing whitespace from the args. - args = trim_blanks(args); - - return c; -} - -/** - * - */ -void CPPPreprocessor:: -handle_define_directive(const string &args, const YYLTYPE &loc) { - if (args.empty()) { - warning("Ignoring empty #define directive", loc); - } else { - CPPManifest *manifest = new CPPManifest(*this, args, loc); - manifest->_vis = preprocessor_vis; - if (!manifest->_has_parameters) { - string expr_string = manifest->expand(); - if (!expr_string.empty()) { - manifest->_expr = parse_expr(expr_string, global_scope, global_scope, loc); - } - } - - std::pair result = - _manifests.insert(Manifests::value_type(manifest->_name, manifest)); - - if (!result.second) { - // There was already a macro with this name. Delete the old. - CPPManifest *other = result.first->second; - if (!manifest->is_equal(other)) { - warning("redefinition of macro '" + manifest->_name + "'", loc); - warning("previous definition is here", other->_loc); - } - result.first->second = manifest; - } - } -} - -/** - * - */ -void CPPPreprocessor:: -handle_undef_directive(const string &args, const YYLTYPE &loc) { - if (args.empty()) { - warning("Ignoring empty #undef directive", loc); - } else { - Manifests::iterator mi = _manifests.find(args); - if (mi != _manifests.end()) { - _manifests.erase(mi); - } - } -} - -/** - * - */ -void CPPPreprocessor:: -handle_ifdef_directive(const string &args, const YYLTYPE &loc) { - if (!is_manifest_defined(args)) { - // The macro is undefined. Skip stuff. - skip_false_if_block(true); - } -} - -/** - * - */ -void CPPPreprocessor:: -handle_ifndef_directive(const string &args, const YYLTYPE &loc) { - if (is_manifest_defined(args)) { - // The macro is defined. Skip stuff. - skip_false_if_block(true); - } -} - -/** - * - */ -void CPPPreprocessor:: -handle_if_directive(const string &args, const YYLTYPE &loc) { - // When expanding manifests, we should replace unknown macros with 0. - string expr = args; - expand_manifests(expr, true); - - int expression_result = 0; - CPPExpressionParser ep(current_scope, global_scope); - ep._verbose = 0; - if (ep.parse_expr(expr, *this)) { - CPPExpression::Result result = ep._expr->evaluate(); - if (result._type == CPPExpression::RT_error) { - std::ostringstream strm; - strm << *ep._expr; - warning("Ignoring invalid expression " + strm.str(), loc); - } else { - expression_result = result.as_integer(); - } - } else { - warning("Ignoring invalid expression " + args, loc); - } - - if (expression_result) { - // The expression result is true. We continue. - return; - } - - // The expression result is false. Skip stuff. - skip_false_if_block(true); -} - -/** - * - */ -void CPPPreprocessor:: -handle_include_directive(const string &args, const YYLTYPE &loc) { - Filename filename; - Filename filename_as_referenced; - bool angle_quotes = false; - - string expr = args; - - // The filename to include might actually be hidden within a manifest - // definition. Wow. FreeType depends on this. - - // Just to play things safe, since our manifest-expansion logic might not - // filter out quotes and angle brackets properly, we'll only expand - // manifests if we don't begin with a quote or bracket. - if (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) { - expand_manifests(expr, false); - } - - if (!expr.empty()) { - if (expr[0] == '"' && expr[expr.size() - 1] == '"') { - filename = expr.substr(1, expr.size() - 2); - - if (_infile->_parent == nullptr) { - // If we're currently processing a top-level file, record the include - // directive. We don't need to record includes from included files. - _quote_includes.insert(filename); - } - } else if (expr[0] == '<' && expr[expr.size() - 1] == '>') { - filename = expr.substr(1, expr.size() - 2); - if (!_noangles) { - // If _noangles is true, we don't make a distinction between angle - // brackets and quote marks--all #include statements are treated the - // same, as if they used quote marks. - angle_quotes = true; - } - - if (_infile->_parent == nullptr) { - // If we're currently processing a top-level file, record the include - // directive. We don't need to record includes from included files. - _angle_includes.insert(filename); - } - } - } else { - warning("Ignoring invalid #include directive", loc); - } - - filename.set_text(); - filename_as_referenced = filename; - - // Now look for the filename. If we didn't use angle quotes, look first in - // the current directory. - CPPFile::Source source = CPPFile::S_none; - - if (find_include(filename, angle_quotes, source)) { - _last_c = '\0'; - - // If it was explicitly named on the command-line, mark it S_local. - filename.make_canonical(); - if (_explicit_files.count(filename)) { - source = CPPFile::S_local; - } - - CPPFile file(filename, filename_as_referenced, source); - - // Don't include it if we included it before and it had #pragma once. - ParsedFiles::const_iterator it = _parsed_files.find(file); - if (it != _parsed_files.end() && it->_pragma_once) { - return; - } - - if (!push_file(file)) { - warning("Unable to read " + filename.get_fullpath(), loc); - } - } else { - warning("Cannot find " + filename.get_fullpath(), loc); - } -} - -/** - * - */ -void CPPPreprocessor:: -handle_pragma_directive(const string &args, const YYLTYPE &loc) { - if (args == "once") { - ParsedFiles::iterator it = _parsed_files.find(loc.file); - assert(it != _parsed_files.end()); - it->_pragma_once = true; - } - - char macro[64]; - if (sscanf(args.c_str(), "push_macro ( \"%63[^\"]\" )", macro) == 1) { - // We just mark it as pushed for now, so that the next time someone tries - // to override it, we save the old value. - Manifests::iterator mi = _manifests.find(macro); - if (mi != _manifests.end()) { - _manifest_stack[macro].push_back(mi->second); - } else { - _manifest_stack[macro].push_back(nullptr); - } - - } else if (sscanf(args.c_str(), "pop_macro ( \"%63[^\"]\" )", macro) == 1) { - ManifestStack &stack = _manifest_stack[macro]; - if (stack.size() > 0) { - CPPManifest *manifest = stack.back(); - stack.pop_back(); - Manifests::iterator mi = _manifests.find(macro); - if (manifest == nullptr) { - // It was undefined when it was pushed, so make it undefined again. - if (mi != _manifests.end()) { - _manifests.erase(mi); - } - } else if (mi != _manifests.end()) { - mi->second = manifest; - } else { - _manifests.insert(Manifests::value_type(macro, manifest)); - } - } else { - warning("pop_macro without matching push_macro", loc); - } - } -} - -/** - * - */ -void CPPPreprocessor:: -handle_error_directive(const string &args, const YYLTYPE &loc) { - error(args, loc); -} - -/** - * We come here when we fail an #if or an #ifdef test, or when we reach the - * #else clause to something we didn't fail. This function skips all text up - * until the matching #endif. - */ -void CPPPreprocessor:: -skip_false_if_block(bool consider_elifs) { - int level = 0; - _save_comments = false; - - int c = skip_comment(get()); - while (c != EOF) { - if (c == '#' && _start_of_line) { - c = skip_whitespace(get()); - - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - loc.last_line = loc.first_line; - loc.last_column = loc.first_column; - - // Is this it? - string command, args; - c = get_preprocessor_command(c, command); - c = get_preprocessor_args(c, args); - if (command == "if" || command == "ifdef" || command == "ifndef") { - // Hmm, a nested if block. Even more to skip. - level++; - } else if (command == "else") { - if (level == 0 && consider_elifs) { - // This will do! - _save_comments = true; - return; - } - } else if (command == "elif") { - if (level == 0 && consider_elifs) { - // If we pass this test, we're in. - _save_comments = true; - handle_if_directive(args, loc); - return; - } - } else if (command == "endif") { - // Skip any args. - if (level == 0) { - // Here's the end! - _save_comments = true; - return; - } - level--; - } - } else { - c = skip_comment(get()); - } - } - - _save_comments = true; -} - -/** - * Returns true if the given manifest is defined. - */ -bool CPPPreprocessor:: -is_manifest_defined(const string &manifest_name) const { - Manifests::const_iterator mi = _manifests.find(manifest_name); - if (mi != _manifests.end()) { - return true; - } - - if (manifest_name == "__has_include" || - manifest_name == "__FILE__" || - manifest_name == "__LINE__") { - // Special built-in directives that are considered "defined". - return true; - } - - return false; -} - -/** - * Locates the given filename. Changes the first argument to the full path. - */ -bool CPPPreprocessor:: -find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) const { - // Now look for the filename. If we didn't use angle quotes, look first in - // the current directory. - if (!angle_quotes && filename.exists()) { - source = CPPFile::S_local; - return true; - } - - // Search the same directory as the includer. - if (!angle_quotes) { - Filename match(get_file()._filename.get_dirname(), filename); - if (match.exists()) { - filename = match; - source = CPPFile::S_alternate; - return true; - } - } - - // Now search the angle-include-path - if (angle_quotes && filename.resolve_filename(_angle_include_path)) { - source = CPPFile::S_system; - return true; - } - - // Now search the quote-include-path - if (!angle_quotes) { - for (size_t dir = 0; dir < _quote_include_path.get_num_directories(); ++dir) { - Filename match(_quote_include_path.get_directory(dir), filename); - if (match.exists()) { - filename = match; - source = _quote_include_kind[dir]; - return true; - } - } - } - - return false; -} - -/** - * - */ -CPPToken CPPPreprocessor:: -get_quoted_char(int c) { - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - - string str = scan_quoted(c); - YYSTYPE result; - if (!str.empty()) { - result.u.integer = (int)str[0]; - } else { - result.u.integer = 0; - } - - return get_literal(CHAR_TOK, loc, str, result); -} - -/** - * - */ -CPPToken CPPPreprocessor:: -get_quoted_string(int c) { - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - - string str = scan_quoted(c); - - return get_literal(SIMPLE_STRING, loc, str); -} - -/** - * - */ -CPPToken CPPPreprocessor:: -get_identifier(int c) { - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - loc.last_line = loc.first_line; - loc.last_column = loc.first_column; - - string name(1, (char)c); - - c = peek(); - while (c != EOF && (isalnum(c) || c == '_')) { - name += get(); - c = peek(); - } - - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - if ((c == '\'' || c == '"') && - (name == "L" || name == "u8" || name == "u" || name == "U" || - name == "R" || name == "LR" || name == "u8R" || name == "uR" || name == "UR")) { - // This is actually a wide-character or wide-string literal or some such. - get(); - string str; - if (name[name.size() - 1] == 'R') { - name.resize(name.size() - 1); - str = scan_raw(c); - } else { - str = scan_quoted(c); - } - - // Figure out the correct character type to use. - CPPExpression::Type type; - if (name == "L") { - type = CPPExpression::T_wstring; - } else if (name == "u8") { - type = CPPExpression::T_u8string; - } else if (name == "u") { - type = CPPExpression::T_u16string; - } else if (name == "U") { - type = CPPExpression::T_u32string; - } else { - type = CPPExpression::T_string; - } - - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - YYSTYPE result; - if (c == '\'') { - // We don't really care about the type for now. - if (!str.empty()) { - result.u.integer = (int)str[0]; - } else { - result.u.integer = 0; - } - return get_literal(CHAR_TOK, loc, str, result); - } else { - result.u.expr = new CPPExpression(str); - result.u.expr->_type = type; - return get_literal(STRING_LITERAL, loc, str, result); - } - } - - _last_c = 0; - - // Is it a manifest? - Manifests::const_iterator mi = _manifests.find(name); - if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) { - // If the manifest is expecting arguments, we don't expand it unless the - // the next token is an open-parenthesis. - CPPManifest *manifest = (*mi).second; - if (manifest->_has_parameters) { - while (c != EOF && isspace(c)) { - get(); - c = peek(); - } - if (c == '(') { - // It is followed by a parenthesis, so we can expand this. - return expand_manifest(manifest, loc); - } - } else { - // Non-function-like macros are always expanded. - return expand_manifest(manifest, loc); - } - } - if (name == "__FILE__") { - return get_literal(SIMPLE_STRING, loc, loc.file._filename_as_referenced); - } - if (name == "__LINE__") { - YYSTYPE result; - result.u.integer = loc.first_line; - return CPPToken(INTEGER, loc, "", result); - } - - // Check for keywords. - auto kwit = keywords.find(name); - int kw = (kwit != keywords.end()) ? (*kwit).second : 0; - - // Update our internal visibility flag. - switch (kw) { - case KW_BEGIN_PUBLISH: - preprocessor_vis = V_published; - break; - - case KW_END_PUBLISH: - preprocessor_vis = V_public; - break; - } - - if (kw != 0) { - if (kw == KW_EXPLICIT || kw == KW_NOEXCEPT) { - // These can be followed by a left-paren. Doing this helps to avoid - // shift/reduce conflicts in the parser. - while (c != EOF && isspace(c)) { - get(); - c = peek(); - } - if (c == '(') { - if (kw == KW_EXPLICIT) { - kw = KW_EXPLICIT_LPAREN; - } - else if (kw == KW_NOEXCEPT) { - kw = KW_NOEXCEPT_LPAREN; - } - get(); - } - } - - YYSTYPE result; - result.u.identifier = nullptr; - return CPPToken(kw, loc, name, result); - } - - return CPPToken(SIMPLE_IDENTIFIER, loc, name); -} - -/** - * Under the assumption that we've just parsed a string or real constant, - * parse a following custom literal, and returns a token for it. - */ -CPPToken CPPPreprocessor:: -get_literal(int token, YYLTYPE loc, const string &str, const YYSTYPE &value) { - string suffix; - - int c = peek(); - if (isalpha(c) || c == '_') { - // A literal seems to be following directly. - while (c != EOF && (isalnum(c) || c == '_')) { - suffix += get(); - c = peek(); - } - } - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - if (suffix.empty()) { - // There is no suffix. - return CPPToken(token, loc, str, value); - } - - // Handle built-in literal suffixes. - if (token == INTEGER) { - if (cmp_nocase(suffix, "u") == 0 || - cmp_nocase(suffix, "l") == 0 || - cmp_nocase(suffix, "ul") == 0 || cmp_nocase(suffix, "lu") == 0 || - cmp_nocase(suffix, "ll") == 0 || - cmp_nocase(suffix, "ull") == 0 || cmp_nocase(suffix, "llu") == 0) { - // These are built-in integer suffixes. Right now, we don't try to - // distinguish between them. - return CPPToken(INTEGER, loc, str, value); - } - } else if (token == REAL) { - if (suffix == "f" || suffix == "F" || - suffix == "l" || suffix == "L") { - return CPPToken(REAL, loc, str, value); - } - } - - // Find the literal operator for this literal. - CPPIdentifier *ident = new CPPIdentifier("operator \"\" " + suffix); - CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope, this); - - if (decl == nullptr) { - // Special case to handle C code, which allows a macro to directly follow - // a string, like "str"SUFFIX. In this case, it becomes a separate token. - Manifests::const_iterator mi = _manifests.find(suffix); - if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) { - CPPManifest *manifest = (*mi).second; - _saved_tokens.push_back(expand_manifest(manifest, loc)); - return CPPToken(token, loc, str, value); - } - } - - if (decl == nullptr || decl->get_subtype() != CPPDeclaration::ST_function_group) { - error("unknown literal suffix " + suffix, loc); - return CPPToken(token, loc, str, value); - } - - // Find the overload with the appropriate signature. - CPPExpression *expr = nullptr; - CPPInstance *instance = nullptr; - CPPInstance *raw_instance = nullptr; - CPPFunctionGroup *fgroup = decl->as_function_group(); - CPPFunctionGroup::Instances::iterator it; - for (it = fgroup->_instances.begin(); it != fgroup->_instances.end(); ++it) { - if ((*it)->_type == nullptr) { - continue; - } - - CPPFunctionType *ftype = (*it)->_type->as_function_type(); - if (ftype == nullptr || ftype->_parameters == nullptr) { - continue; - } - - CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters; - if (token == STRING_LITERAL || token == SIMPLE_STRING) { - // A custom string literal must take a second size_t argument. - if (params.size() != 2) continue; - } else { - if (params.size() != 1) continue; - } - - CPPInstance *param = params[0]; - if (param == nullptr || param->_type == nullptr) { - continue; - } - - CPPType *type = param->_type; - while (type->get_subtype() == CPPDeclaration::ST_const) { - type = type->as_const_type()->_wrapped_around; - } - if (type->get_subtype() == CPPDeclaration::ST_simple) { - // It's a primitive type. Check that it matches the appropriate token. - CPPSimpleType::Type simple = type->as_simple_type()->_type; - - if (token == INTEGER && simple == CPPSimpleType::T_int) { - expr = new CPPExpression(value.u.integer); - instance = (*it); - break; - } else if (token == REAL && simple == CPPSimpleType::T_double) { - expr = new CPPExpression(value.u.real); - instance = (*it); - break; - } else if (token == CHAR_TOK && (simple == CPPSimpleType::T_char || - simple == CPPSimpleType::T_wchar_t || - simple == CPPSimpleType::T_char8_t || - simple == CPPSimpleType::T_char16_t || - simple == CPPSimpleType::T_char32_t)) { - // We currently don't have the means to check the exact character - // type. - expr = new CPPExpression(value.u.integer); - instance = (*it); - break; - } - - } else if (type->get_subtype() == CPPDeclaration::ST_pointer) { - // Must be a const pointer. Unwrap it. - type = type->as_pointer_type()->_pointing_at; - if (type == nullptr || type->get_subtype() != CPPDeclaration::ST_const) { - continue; - } - type = type->as_const_type()->_wrapped_around; - if (type == nullptr || type->get_subtype() != CPPDeclaration::ST_simple) { - continue; - } - - CPPSimpleType::Type simple = type->as_simple_type()->_type; - if (simple == CPPSimpleType::T_char && params.size() == 1) { - // This is the raw literal operator. Store it, but don't break; a - // non-raw version of the operator might follow, which we'd prefer. - raw_instance = (*it); - - } else if (token == SIMPLE_STRING && simple == CPPSimpleType::T_char) { - expr = new CPPExpression(str); - instance = (*it); - break; - - } else if (token == STRING_LITERAL) { - // Verify that the character type of the string literal matches the - // character type of the parameter. - CPPExpression::Type str_type = value.u.expr->_type; - if ((str_type == CPPExpression::T_string && simple == CPPSimpleType::T_char) || - (str_type == CPPExpression::T_wstring && simple == CPPSimpleType::T_wchar_t) || - (str_type == CPPExpression::T_u8string && (simple == CPPSimpleType::T_char || simple == CPPSimpleType::T_char8_t)) || - (str_type == CPPExpression::T_u16string && simple == CPPSimpleType::T_char16_t) || - (str_type == CPPExpression::T_u32string && simple == CPPSimpleType::T_char32_t)) { - expr = value.u.expr; - instance = (*it); - break; - } - } - } - } - - YYSTYPE result; - if (instance != nullptr) { - result.u.expr = new CPPExpression(CPPExpression::literal(expr, instance)); - return CPPToken(CUSTOM_LITERAL, loc, str, result); - } - - if ((token == REAL || token == INTEGER) && raw_instance != nullptr) { - // For numeric constants, we can fall back to a raw literal operator. - result.u.expr = new CPPExpression(CPPExpression::raw_literal(str, instance)); - return CPPToken(CUSTOM_LITERAL, loc, str, result); - } - - error(fgroup->_name + " has no suitable overload for literal of this type", loc); - result.u.expr = nullptr; - return CPPToken(CUSTOM_LITERAL, loc, str, result); -} - -/** - * - */ -CPPToken CPPPreprocessor:: -expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc) { - vector_string args; - - if (manifest->_has_parameters) { - // Hmm, we're expecting arguments. - extract_manifest_args(manifest->_name, manifest->_num_parameters, - manifest->_variadic_param, args); - } - - // Keep track of the manifests we're supposed to ignore. - CPPManifest::Ignores ignores; - ignores.insert(manifest); - - InputFile *infile = _infile; - while (infile != nullptr) { - if (infile->_ignore_manifest) { - ignores.insert(infile->_manifest); - } - infile = infile->_parent; - } - - string expanded = " " + manifest->expand(args, false, ignores) + " "; - push_expansion(expanded, manifest, loc); - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Expanding " << manifest->_name << " to " << expanded << "\n"; -#endif - - return internal_get_next_token(); -} - -/** - * - */ -void CPPPreprocessor:: -extract_manifest_args(const string &name, int num_args, int va_arg, - vector_string &args) { - CPPFile first_file = get_file(); - int first_line = get_line_number(); - int first_col = get_col_number(); - - // Skip whitespace till paren. - int c = _last_c; - _last_c = '\0'; - if (c == 0) { - c = get(); - } - while (c != EOF && isspace(c)) { - c = get(); - } - - if (c != '(') { - // No paren, so we have only one arg. - string arg; - while (c != EOF && (isalnum(c) || c == '_')) { - arg += c; - c = get(); - } - args.push_back(arg); - - } else { - // Skip paren. - c = skip_whitespace(get()); - int paren_level = 1; - string arg; - while (c != EOF) { - if (c == ',' && paren_level == 1) { - args.push_back(trim_blanks(arg)); - arg = ""; - c = get(); - - } else if (c == '"' || c == '\'') { - // Quoted string or character. - int quote_mark = c; - arg += c; - c = get(); - while (c != EOF && c != quote_mark && c != '\n') { - if (c == '\\') { - arg += c; - c = get(); - } - if (c != EOF) { - arg += c; - c = get(); - } - } - arg += c; - c = get(); - - } else if (c == '(') { - arg += '('; - ++paren_level; - c = get(); - - } else if (c == ')') { - --paren_level; - if (paren_level == 0) { - break; - } - arg += ')'; - c = get(); - - } else if (isspace(c)) { - // Skip extra whitespace. - c = skip_whitespace(c); - if (!arg.empty()) { - arg += ' '; - } - - } else if (c == '\\') { - // It could be a slash before a newline. If so, that's whitespace as - // well. - c = get(); - if (c != '\n') { - arg += '\\'; - } else if (!arg.empty()) { - arg += ' '; - c = skip_whitespace(get()); - } - - } else { - arg += c; - c = get(); - } - } - if (num_args != 0 || !arg.empty()) { - args.push_back(trim_blanks(arg)); - } - } - - YYLTYPE loc; - loc.first_line = first_line; - loc.first_column = first_col; - loc.last_line = first_line; - loc.last_column = first_col; - loc.file = first_file; - - if ((int)args.size() < num_args - (va_arg >= 0)) { - warning("Not enough arguments for manifest " + name, loc); - - } else if (va_arg < 0 && (int)args.size() > num_args) { - warning("Too many arguments for manifest " + name, loc); - } -} - -/** - * Expands the defined(manifest) function to either 1 or 0, depending on - * whether the manifest exists. - */ -void CPPPreprocessor:: -expand_defined_function(string &expr, size_t q, size_t &p) const { - while (p < expr.size() && isspace(expr[p])) { - p++; - } - - bool has_paren = false; - if (expr[p] == '(') { - has_paren = true; - p++; - } - - size_t r = p; - while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { - p++; - } - string name = expr.substr(r, p - r); - - if (has_paren) { - if (expr[p] == ')') { - p++; - } else { - error("missing ')' after 'defined'"); - } - } - - char result = is_manifest_defined(name) ? '1' : '0'; - expr = expr.substr(0, q) + result + expr.substr(p); - p = q + 1; -} - -/** - * Expands the __has_include(manifest) function to either 1 or 0, depending on - * whether the include file exists. - */ -void CPPPreprocessor:: -expand_has_include_function(string &expr, size_t q, size_t &p) const { - bool found_file = false; - - // Skip whitespace till paren. - while (p < expr.size() && isspace(expr[p])) { - p++; - } - - if (expr[p] != '(') { - error("expected '(' after '__has_include'"); - return; - } - p++; - while (p < expr.size() && isspace(expr[p])) { - p++; - } - - int paren_level = 1; - bool needs_expansion = false; - size_t r = p; - while (p < expr.size()) { - if (expr[p] == '"' || expr[p] == '\'' || expr[p] == '<') { - // Quoted string or angle bracket. - int quote_mark = expr[p]; - if (quote_mark == '<') { - quote_mark = '>'; - } - p++; - while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { - if (expr[p] == '\\') { - p++; - } - if (p < expr.size()) { - p++; - } - } - } - else if (expr[p] == '(') { - ++paren_level; - } - else if (expr[p] == ')') { - --paren_level; - if (paren_level == 0) { - break; - } - } - else if (isalnum(expr[p]) || expr[p] == '_') { - needs_expansion = true; - } - p++; - } - - if (p >= expr.size() || expr[p] != ')') { - error("missing ')' after '__has_include'"); - return; - } - - // Back up to strip trailing whitespace. - size_t t = p; - while (t > r && isspace(expr[t - 1])) { - --t; - } - string inc = expr.substr(r, t - r); - p++; - - // Only expand if we've encountered unquoted identifier-valid characters, - // to be on the safe side. - if (needs_expansion) { - expand_manifests(inc, false); - } - - Filename filename; - bool angle_quotes = false; - - if (!inc.empty() && inc[0] == '"' && inc[inc.size() - 1] == '"') { - filename = inc.substr(1, inc.size() - 2); - } - else if (!inc.empty() && inc[0] == '<' && inc[inc.size() - 1] == '>') { - filename = inc.substr(1, inc.size() - 2); - if (!_noangles) { - // If _noangles is true, we don't make a distinction between angle - // brackets and quote marks--all #inc statements are treated the - // same, as if they used quote marks. - angle_quotes = true; - } - } - else { - warning("invalid argument for __has_include() directive: " + inc); - expr = expr.substr(0, q) + "0" + expr.substr(p); - p = q + 1; - return; - } - - filename.set_text(); - - CPPFile::Source source = CPPFile::S_none; - found_file = find_include(filename, angle_quotes, source); - - string result = found_file ? "1" : "0"; - expr = expr.substr(0, q) + result + expr.substr(p); - p = q + result.size(); -} - -/** - * Assuming that we've just read a digit or a period indicating the start of a - * number, read the rest. - */ -CPPToken CPPPreprocessor:: -get_number(int c) { - YYLTYPE loc; - loc.file = get_file(); - loc.first_line = get_line_number(); - loc.first_column = get_col_number(); - loc.last_line = loc.first_line; - loc.last_column = loc.first_column; - - string num(1, (char)c); - bool leading_zero = (c == '0'); - bool decimal_point = (c == '.'); - - c = skip_digit_separator(peek()); - - if (leading_zero && (c == 'x' || c == 'X')) { - // Here we have a hex number. - num += get(); - c = peek(); - - while (c != EOF && (isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f'))) { - num += get(); - c = skip_digit_separator(peek()); - } - - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - YYSTYPE result; - result.u.integer = strtol(num.c_str(), nullptr, 16); - - return get_literal(INTEGER, loc, num, result); - - } else if (leading_zero && (c == 'b' || c == 'B')) { - // A C++14-style binary number. - get(); - c = peek(); - string bin(1, (char)c); - - while (c != EOF && (c == '0' || c == '1')) { - bin += get(); - c = skip_digit_separator(peek()); - } - - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - YYSTYPE result; - result.u.integer = strtol(bin.c_str(), nullptr, 2); - - return get_literal(INTEGER, loc, bin, result); - } - - while (c != EOF && isdigit(c)) { - num += get(); - c = skip_digit_separator(peek()); - } - - if (c == '.' && !decimal_point) { - // Now we have a floating-point number. - decimal_point = true; - num += get(); - c = peek(); - - while (c != EOF && isdigit(c)) { - num += get(); - c = peek(); - } - } - - if (decimal_point || c == 'e' || c == 'E') { - if (tolower(c) == 'e') { - // An exponent is allowed. - num += get(); - c = peek(); - if (c == '-' || c == '+') { - num += get(); - c = peek(); - } - while (c != EOF && isdigit(c)) { - num += get(); - c = skip_digit_separator(peek()); - } - } - - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - YYSTYPE result; - result.u.real = (long double)pstrtod(num.c_str(), nullptr); - - return get_literal(REAL, loc, num, result); - } - - // This is a decimal or octal integer number. - - loc.last_line = get_line_number(); - loc.last_column = get_col_number(); - - YYSTYPE result; - - if (leading_zero) { - // A leading zero implies an octal number. strtol() is supposed to be - // able to make this distinction by itself, but we'll do it explicitly - // just to be sure. - result.u.integer = strtol(num.c_str(), nullptr, 8); - - } else { - // A decimal (base 10) integer. - result.u.integer = strtol(num.c_str(), nullptr, 10); - } - - return get_literal(INTEGER, loc, num, result); -} - -/** - * - */ -int CPPPreprocessor:: -scan_escape_sequence(int c) { - if (c != '\\') { - return c; - } - - c = get(); - switch (c) { - case 'a': - return '\a'; - - case 'b': - return '\b'; - - case 'f': - return '\f'; - - case 'n': - return '\n'; - - case 'r': - return '\r'; - - case 't': - return '\t'; - - case 'v': - return '\v'; - - case 'e': - // \e is non-standard, but GCC supports it. - return '\x1B'; - - case 'x': - // hex character. - c = get(); - if (isxdigit(c)) { - int val = hex_val(c); - if (isxdigit(peek())) { - val = (val << 4) | hex_val(get()); - } - return val; - } - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - // Octal character. - { - int val = (c - '0'); - c = peek(); - if (c >= '0' && c <= '7') { - val = (val << 3) | (get() - '0'); - c = peek(); - if (c >= '0' && c <= '7') { - val = (val << 3) | (get() - '0'); - } - } - return val; - } - } - - // Simply output the following character. - return c; -} - -/** - * - */ -string CPPPreprocessor:: -scan_quoted(int c) { - int quote_mark = c; - - string str; - c = get(); - while (c != EOF && c != '\n' && c != quote_mark) { - if (c == '\\') { - // Backslash means a special character follows. - c = scan_escape_sequence(c); - } - - str += c; - c = get(); - } - - if (c != quote_mark) { - warning("Unclosed string"); - } - return str; -} - -/** - * Parses a C++11 raw string. - */ -string CPPPreprocessor:: -scan_raw(int c) { - int quote_mark = c; - - string delimiter = ")"; - - string str; - c = get(); - while (c != EOF && c != '(') { - delimiter += c; - c = get(); - } - - // OK, now start parsing the string, until we see the delimiter again. - c = get(); - while (c != EOF) { - if (c == quote_mark) { - // We encountered a quote mark - did the last part of the string end - // with the given delimiter? If so, we've reached the end. - if (str.compare(str.size() - delimiter.size(), delimiter.size(), delimiter) == 0) { - str.resize(str.size() - delimiter.size()); - break; - } - } - str += c; - c = get(); - } - - if (c != quote_mark) { - warning("Unclosed string"); - } - return str; -} - -/** - * Returns true if the manifest is one that is being ignored right now - * (presumably because we are presently expanding it). - */ -bool CPPPreprocessor:: -should_ignore_manifest(const CPPManifest *manifest) const { - InputFile *infile = _infile; - while (infile != nullptr) { - if (infile->_ignore_manifest && infile->_manifest == manifest) { - return true; - } - infile = infile->_parent; - } - - return false; -} - -/** - * Returns true if we should ignore any preprocessor directives (e.g. we're - * presently expanding a manifest). - */ -bool CPPPreprocessor:: -should_ignore_preprocessor() const { - InputFile *infile = _infile; - while (infile != nullptr) { - if (infile->_ignore_manifest) { - return true; - } - infile = infile->_parent; - } - - return false; -} - -/** - * - */ -int CPPPreprocessor:: -get() { - if (_unget != '\0') { - int c = _unget; - _unget = '\0'; - return c; - } - - if (UNLIKELY(_infile == nullptr)) { - return EOF; - } - - int c = _infile->get(); - - while (UNLIKELY(c == EOF && _infile != nullptr)) { -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "End of input stream, restoring to previous input\n"; -#endif - // Pop the last file off the end. - InputFile *infile = _infile; - _infile = infile->_parent; - delete infile; - - // Synthesize a newline, just in case the file doesn't already end with - // one. - c = '\n'; - } - - if (c == '\n') { - _start_of_line = true; - } else if (!isspace(c) && c != '#') { - _start_of_line = false; - } - - return c; -} - -/** - * Like get(), but does not alter the current state. - */ -int CPPPreprocessor:: -peek() { - if (_unget != '\0') { - return _unget; - } - - InputFile *infile = _infile; - if (UNLIKELY(infile == nullptr)) { - return EOF; - } - - int c = infile->peek(); - - while (UNLIKELY(c == EOF && infile != nullptr)) { - int last_c = infile->_prev_last_c; - infile = infile->_parent; - - if (last_c != '\0') { - c = last_c; - } else if (infile != nullptr) { - c = infile->peek(); - } - } - - return c; -} - -/** - * Undoes the effects of a previous get(). Not recommended, use peek() - * instead where possible, as it doesn't cause the column index to be off. - */ -void CPPPreprocessor:: -unget(int c) { - assert(_unget == '\0'); - _unget = c; -} - -/** - * Recursively invokes yacc to parse the stuff within angle brackets that's - * the template instantiation part of an identifier. This involves setting - * and restoring some state flags so we can return EOF when we reach the - * closing bracket. - */ -CPPTemplateParameterList *CPPPreprocessor:: -nested_parse_template_instantiation(CPPTemplateScope *scope) { -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Beginning nested parse\n"; -#endif - assert(scope != nullptr); - - State old_state = _state; - int old_nesting = _paren_nesting; - bool old_parsing_params = _parsing_template_params; - - const CPPTemplateParameterList &formal_params = scope->_parameters; - CPPTemplateParameterList::Parameters::const_iterator pi; - - _state = S_nested; - _paren_nesting = 0; - _parsing_template_params = true; - - CPPToken token = internal_get_next_token(); - if (token._token == '>' || token._token == 0) { - _parsing_template_params = false; - } else { - _saved_tokens.push_back(token); - } - - CPPTemplateParameterList *actual_params = new CPPTemplateParameterList; - - for (pi = formal_params._parameters.begin(); - pi != formal_params._parameters.end() && _parsing_template_params;) { - CPPToken token = peek_next_token(); - YYLTYPE loc = token._lloc; - - CPPDeclaration *decl = (*pi); - CPPClassTemplateParameter *param = decl->as_class_template_parameter(); - CPPInstance *inst = decl->as_instance(); - if (param) { - // Parse a typename template parameter. - _saved_tokens.push_back(CPPToken(START_TYPE)); - CPPType *type = ::parse_type(this, current_scope, global_scope); - if (type == nullptr) { - loc.last_line = get_line_number(); - loc.last_column = get_col_number() - 1; - warning("invalid type", loc); - skip_to_end_nested(); - type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); - } - actual_params->_parameters.push_back(type); - - // If this is a variadic template, keep reading using this parameter. - if (!param->_packed) { - ++pi; - } - } else if (inst) { - // Parse a constant expression template parameter. - _saved_tokens.push_back(CPPToken(START_CONST_EXPR)); - CPPExpression *expr = parse_const_expr(this, current_scope, global_scope); - if (expr == nullptr) { - loc.last_line = get_line_number(); - loc.last_column = get_col_number() - 1; - warning("invalid expression", loc); - skip_to_end_nested(); - expr = new CPPExpression(0); - } - actual_params->_parameters.push_back(expr); - - // If this is a variadic template, keep reading using this parameter. - if ((inst->_storage_class & CPPInstance::SC_parameter_pack) == 0) { - ++pi; - } - } else { - loc.last_line = get_line_number(); - loc.last_column = get_col_number() - 1; - warning("invalid template parameter", loc); - skip_to_end_nested(); - ++pi; - } - - _state = S_nested; - _paren_nesting = 0; - } - - if (_parsing_template_params) { - warning("Ignoring extra parameters in template instantiation"); - skip_to_angle_bracket(); - } - - _state = old_state; - _paren_nesting = old_nesting; - _parsing_template_params = old_parsing_params; - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Ending nested parse\n"; -#endif - return actual_params; -} - - -/** - * This is an error-recovery function, called after returning from a nested - * parse. If the state is not S_end_nested, there was an error in parsing the - * nested tokens, and not all of the nested tokens may have been consumed. - * This function will consume the rest of the nested tokens. - */ -void CPPPreprocessor:: -skip_to_end_nested() { -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Skipping tokens:\n"; -#endif - - // Eat any eof tokens on the pushback stack. - while (!_saved_tokens.empty() && _saved_tokens.back().is_eof()) { - _saved_tokens.pop_back(); - } - - while (_state != S_end_nested && _state != S_eof) { - get_next_token(); - } - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Done skipping tokens.\n"; -#endif -} - -/** - * This is an error-recovery function, called after returning from a nested - * parse. If we haven't yet consumed the closing angle bracket on the - * template instantiation, keep consuming tokens until we do. - */ -void CPPPreprocessor:: -skip_to_angle_bracket() { -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Skipping tokens:\n"; -#endif - - while (_parsing_template_params && _state != S_eof) { - _state = S_nested; - while (_state != S_end_nested && _state != S_eof) { - get_next_token(); - } - } - - // Eat any eof tokens on the pushback stack. - while (!_saved_tokens.empty() && _saved_tokens.back().is_eof()) { - _saved_tokens.pop_back(); - } - -#ifdef CPP_VERBOSE_LEX - indent(cerr, get_file_depth() * 2) - << "Done skipping tokens.\n"; -#endif -} - -/** - * Returns the number of files on the _infile list. - */ -int CPPPreprocessor:: -get_file_depth() const{ - int depth = 0; - InputFile *infile = _infile; - while (infile != nullptr) { - ++depth; - infile = infile->_parent; - } - return depth; -} diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h deleted file mode 100644 index a241fc617d..0000000000 --- a/dtool/src/cppparser/cppPreprocessor.h +++ /dev/null @@ -1,235 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppPreprocessor.h - * @author drose - * @date 1999-10-22 - */ - -#ifndef CPPPREPROCESSOR_H -#define CPPPREPROCESSOR_H - -#include "dtoolbase.h" - -#include "cppManifest.h" -#include "cppToken.h" -#include "cppFile.h" -#include "cppCommentBlock.h" - -#include "dSearchPath.h" -#include "vector_string.h" - -#include -#include -#include - -class CPPScope; -class CPPTemplateParameterList; -class CPPExpression; - -// #define CPP_VERBOSE_LEX - -/** - * - */ -class CPPPreprocessor { -public: - CPPPreprocessor(); - - bool preprocess_file(const Filename &filename); - - void set_verbose(int verbose); - int get_verbose() const; - - void copy_filepos(const CPPPreprocessor &other); - - CPPFile get_file() const; - int get_line_number() const; - int get_col_number() const; - - CPPToken get_next_token(); - CPPToken peek_next_token(); -#ifdef CPP_VERBOSE_LEX - CPPToken get_next_token0(); - int _token_index; -#endif - - void warning(const std::string &message) const; - void warning(const std::string &message, const YYLTYPE &loc) const; - void error(const std::string &message) const; - void error(const std::string &message, const YYLTYPE &loc) const; - void show_line(const YYLTYPE &loc) const; - - CPPCommentBlock *get_comment_before(int line, CPPFile file); - CPPCommentBlock *get_comment_on(int line, CPPFile file); - - int get_warning_count() const; - int get_error_count() const; - - typedef std::unordered_map Manifests; - Manifests _manifests; - - typedef std::vector ManifestStack; - std::map _manifest_stack; - - std::vector _quote_include_kind; - DSearchPath _quote_include_path; - DSearchPath _angle_include_path; - bool _noangles; - - CPPComments _comments; - - typedef std::set ParsedFiles; - ParsedFiles _parsed_files; - - typedef std::set Includes; - Includes _quote_includes; - Includes _angle_includes; - - std::set _explicit_files; - - // This is normally true, to indicate that the preprocessor should decode - // identifiers like foo::bar into a single IDENTIFIER, - // TYPENAME_IDENTIFIER, or SCOPING token for yacc's convenience. When - // false, it leaves them alone and returns a sequence of SIMPLE_IDENTIFIER - // and SCOPE tokens instead. - bool _resolve_identifiers; - - // The default _verbose level is 1, which will output normal error and - // warning messages but nothing else. Set this to 0 to make the warning - // messages go away (although the counts will still be incremented), or set - // it higher to get more debugging information. - int _verbose; - - // The location of the last token. - cppyyltype _last_token_loc; - -protected: - bool init_cpp(const CPPFile &file); - bool init_const_expr(const std::string &expr); - bool init_type(const std::string &type); - bool push_file(const CPPFile &file); - bool push_string(const std::string &input); - bool push_expansion(const std::string &input, const CPPManifest *manifest, - const YYLTYPE &loc); - -public: - void expand_manifests(std::string &expr, bool expand_undefined = false, - const CPPManifest::Ignores &ignores = CPPManifest::Ignores()) const; - CPPExpression *parse_expr(const std::string &expr, CPPScope *current_scope, - CPPScope *global_scope, const YYLTYPE &loc); - -private: - CPPToken internal_get_next_token(); - int check_digraph(int c); - int check_trigraph(int c); - int skip_whitespace(int c); - int skip_comment(int c); - int skip_c_comment(int c); - int skip_cpp_comment(int c); - int skip_digit_separator(int c); - int process_directive(int c); - - int get_preprocessor_command(int c, std::string &command); - int get_preprocessor_args(int c, std::string &args); - - void handle_define_directive(const std::string &args, const YYLTYPE &loc); - void handle_undef_directive(const std::string &args, const YYLTYPE &loc); - void handle_ifdef_directive(const std::string &args, const YYLTYPE &loc); - void handle_ifndef_directive(const std::string &args, const YYLTYPE &loc); - void handle_if_directive(const std::string &args, const YYLTYPE &loc); - void handle_include_directive(const std::string &args, const YYLTYPE &loc); - void handle_pragma_directive(const std::string &args, const YYLTYPE &loc); - void handle_error_directive(const std::string &args, const YYLTYPE &loc); - - void skip_false_if_block(bool consider_elifs); - bool is_manifest_defined(const std::string &manifest_name) const; - bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) const; - - CPPToken get_quoted_char(int c); - CPPToken get_quoted_string(int c); - CPPToken get_identifier(int c); - CPPToken get_literal(int token, YYLTYPE loc, const std::string &str, - const YYSTYPE &result = YYSTYPE()); - CPPToken expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc); - void r_expand_manifests(std::string &expr, bool expand_undefined, - const YYLTYPE &loc, std::set &expanded); - void extract_manifest_args(const std::string &name, int num_args, - int va_arg, vector_string &args); - void expand_defined_function(std::string &expr, size_t q, size_t &p) const; - void expand_has_include_function(std::string &expr, size_t q, size_t &p) const; - - CPPToken get_number(int c); - int scan_escape_sequence(int c); - std::string scan_quoted(int c); - std::string scan_raw(int c); - - bool should_ignore_manifest(const CPPManifest *manifest) const; - bool should_ignore_preprocessor() const; - - int get(); - int peek(); - void unget(int c); - - CPPTemplateParameterList * - nested_parse_template_instantiation(CPPTemplateScope *scope); - void skip_to_end_nested(); - void skip_to_angle_bracket(); - - int get_file_depth() const; - - class InputFile { - public: - InputFile(); - ~InputFile(); - - bool open(const CPPFile &file); - bool connect_input(const std::string &input); - int get(); - int peek(); - - const CPPManifest *_manifest; - CPPFile _file; - std::string _input; - std::istream *_in; - int _line_number; - int _col_number; - int _next_line_number; - int _next_col_number; - bool _lock_position; - bool _ignore_manifest; - int _prev_last_c; - - InputFile *_parent = nullptr; - }; - - InputFile *_infile = nullptr; - - enum State { - S_normal, S_eof, S_nested, S_end_nested - }; - State _state; - int _paren_nesting; - bool _parsing_template_params; - bool _parsing_attribute; - - bool _start_of_line; - int _unget; - - int _last_c; - bool _last_cpp_comment; - bool _save_comments; - - std::vector _saved_tokens; - - mutable int _warning_count; - mutable int _error_count; - bool _error_abort; -}; - -#endif diff --git a/dtool/src/cppparser/cppReferenceType.cxx b/dtool/src/cppparser/cppReferenceType.cxx deleted file mode 100644 index 100111eac2..0000000000 --- a/dtool/src/cppparser/cppReferenceType.cxx +++ /dev/null @@ -1,296 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppReferenceType.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppReferenceType.h" -#include "cppTypedefType.h" -#include "cppStructType.h" - -/** - * - */ -CPPReferenceType:: -CPPReferenceType(CPPType *pointing_at, ValueCategory vcat) : - CPPType(CPPFile()), - _pointing_at(pointing_at), - _value_category(vcat) -{ -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPReferenceType:: -is_fully_specified() const { - return CPPType::is_fully_specified() && - _pointing_at->is_fully_specified(); -} - -/** - * - */ -CPPDeclaration *CPPReferenceType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - return (*si).second; - } - - CPPReferenceType *rep = new CPPReferenceType(*this); - rep->_pointing_at = - _pointing_at->substitute_decl(subst, current_scope, global_scope) - ->as_type(); - - if (rep->_pointing_at == _pointing_at) { - delete rep; - rep = this; - } - rep = CPPType::new_type(rep)->as_reference_type(); - subst.insert(SubstDecl::value_type(this, rep)); - return rep; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPReferenceType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *ptype = _pointing_at->resolve_type(current_scope, global_scope); - - if (ptype != _pointing_at) { - CPPReferenceType *rep = new CPPReferenceType(*this); - rep->_pointing_at = ptype; - return CPPType::new_type(rep); - } - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPReferenceType:: -is_tbd() const { - return _pointing_at->is_tbd(); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPReferenceType:: -is_standard_layout() const { - return false; -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPReferenceType:: -is_trivial() const { - return false; -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPReferenceType:: -is_trivially_copyable() const { - return false; -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPReferenceType:: -is_constructible(const CPPType *given_type) const { - const CPPType *a; - const CPPType *b; - - CPPReferenceType *ref_type = ((CPPType *)given_type)->as_reference_type(); - if (ref_type != nullptr) { - if (ref_type->_value_category == VC_rvalue) { - return is_constructible(ref_type->_pointing_at); - } - - if (_value_category == VC_rvalue) { - // Can never initialize an rvalue ref from an lvalue ref. - return false; - } - - if (!_pointing_at->is_const()) { - // Cannot initialize a non-const reference using a const one. - if (ref_type->_pointing_at->is_const()) { - return false; - } - } - - a = _pointing_at->remove_cv(); - b = ref_type->_pointing_at->remove_cv(); - - } else { - // Initializing using an rvalue. - if (!_pointing_at->is_const()) { - // Cannot initialize a non-const reference using a const one. - if (given_type->is_const()) { - return false; - } - - // Cannot initalise a non-const lvalue reference with an rvalue ref. - if (_value_category == VC_lvalue) { - return false; - } - } - - a = _pointing_at->remove_cv(); - b = ((CPPType *)given_type)->remove_cv(); - } - - if (a == b || *a == *b) { - return true; - } - - // Can initialize from derived class pointer. - const CPPStructType *a_struct = a->as_struct_type(); - const CPPStructType *b_struct = b->as_struct_type(); - if (a_struct != nullptr && b_struct != nullptr) { - return a_struct->is_base_of(b_struct); - } - - return false; -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPReferenceType:: -is_default_constructible() const { - return false; -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPReferenceType:: -is_copy_constructible() const { - return (_value_category == VC_lvalue); -} - -/** - * Returns true if the type is destructible. - */ -bool CPPReferenceType:: -is_destructible() const { - return false; -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPReferenceType:: -is_equivalent(const CPPType &other) const { - const CPPReferenceType *ot = ((CPPType *)&other)->as_reference_type(); - if (ot == nullptr) { - return CPPType::is_equivalent(other); - } - - return _pointing_at->is_equivalent(*ot->_pointing_at); -} - -/** - * - */ -void CPPReferenceType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - /* - _pointing_at->output(out, indent_level, scope, complete); - out << " &"; - */ - output_instance(out, indent_level, scope, complete, "", ""); -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPReferenceType:: -output_instance(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const { - - std::string prefix((_value_category == VC_rvalue) ? "&&" : "&"); - - if (!_attributes.is_empty()) { - std::ostringstream strm; - strm << prefix << _attributes << " "; - prefix = strm.str(); - } - - _pointing_at->output_instance(out, indent_level, scope, complete, - prefix + prename, name); -} - -/** - * - */ -CPPDeclaration::SubType CPPReferenceType:: -get_subtype() const { - return ST_reference; -} - -/** - * - */ -CPPReferenceType *CPPReferenceType:: -as_reference_type() { - return this; -} - - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPReferenceType:: -is_equal(const CPPDeclaration *other) const { - const CPPReferenceType *ot = ((CPPDeclaration *)other)->as_reference_type(); - assert(ot != nullptr); - - return (_pointing_at == ot->_pointing_at) && - (_value_category == ot->_value_category); -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPReferenceType:: -is_less(const CPPDeclaration *other) const { - const CPPReferenceType *ot = ((CPPDeclaration *)other)->as_reference_type(); - assert(ot != nullptr); - - if (_value_category != ot->_value_category) { - return (_value_category < ot->_value_category); - } - - return _pointing_at < ot->_pointing_at; -} diff --git a/dtool/src/cppparser/cppReferenceType.h b/dtool/src/cppparser/cppReferenceType.h deleted file mode 100644 index df79a1ec21..0000000000 --- a/dtool/src/cppparser/cppReferenceType.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppReferenceType.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPREFERENCETYPE_H -#define CPPREFERENCETYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -/** - * Either an lvalue- or rvalue-reference. - */ -class CPPReferenceType : public CPPType { -public: - enum ValueCategory { - VC_lvalue, - VC_rvalue - }; - - CPPReferenceType(CPPType *pointing_at, ValueCategory vcat=VC_lvalue); - - CPPType *_pointing_at; - ValueCategory _value_category; - - virtual bool is_fully_specified() const; - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_destructible() const; - virtual bool is_equivalent(const CPPType &other) const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - - virtual SubType get_subtype() const; - - virtual CPPReferenceType *as_reference_type(); - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppScope.cxx b/dtool/src/cppparser/cppScope.cxx deleted file mode 100644 index a88961d4b7..0000000000 --- a/dtool/src/cppparser/cppScope.cxx +++ /dev/null @@ -1,1191 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppScope.cxx - * @author drose - * @date 1999-10-21 - */ - -#include "cppScope.h" -#include "cppParser.h" -#include "cppDeclaration.h" -#include "cppNamespace.h" -#include "cppTypedefType.h" -#include "cppTypeDeclaration.h" -#include "cppExtensionType.h" -#include "cppEnumType.h" -#include "cppInstance.h" -#include "cppInstanceIdentifier.h" -#include "cppIdentifier.h" -#include "cppStructType.h" -#include "cppFunctionGroup.h" -#include "cppPreprocessor.h" -#include "cppTemplateScope.h" -#include "cppClassTemplateParameter.h" -#include "cppFunctionType.h" -#include "cppConstType.h" -#include "cppUsing.h" -#include "cppBisonDefs.h" -#include "indent.h" - -using std::ostream; -using std::ostringstream; -using std::pair; -using std::string; - -/** - * - */ -CPPScope:: -CPPScope(CPPScope *parent_scope, - const CPPNameComponent &name, CPPVisibility starting_vis) : - _name(name), - _parent_scope(parent_scope), - _current_vis(starting_vis) -{ - _struct_type = nullptr; - _is_fully_specified = false; - _fully_specified_known = false; - _is_fully_specified_recursive_protect = false; - _subst_decl_recursive_protect = false; -} - -/** - * - */ -CPPScope:: -~CPPScope() { -} - -/** - * Sets the struct or class that owns this scope. This should only be done - * once, when the scope and its associated struct are created. It's provided - * so the scope can check the struct's ancestry for inherited symbols. - */ -void CPPScope:: -set_struct_type(CPPStructType *struct_type) { - _struct_type = struct_type; -} - -/** - * Returns the class or struct that defines this scope, if any. - */ -CPPStructType *CPPScope:: -get_struct_type() const { - return _struct_type; -} - -/** - * Returns the parent scope of this scope, if any. - */ -CPPScope *CPPScope:: -get_parent_scope() const { - return _parent_scope; -} - -/** - * - */ -void CPPScope:: -set_current_vis(CPPVisibility current_vis) { - _current_vis = current_vis; -} - -/** - * - */ -CPPVisibility CPPScope:: -get_current_vis() const { - return _current_vis; -} - -/** - * - */ -void CPPScope:: -add_declaration(CPPDeclaration *decl, CPPScope *global_scope, - CPPPreprocessor *preprocessor, const cppyyltype &pos) { - decl->_vis = _current_vis; - - // Get the recent comments from the preprocessor. These are the comments - // that appeared preceding this particular declaration; they might be - // relevant to the declaration. - - if (decl->_leading_comment == nullptr) { - decl->_leading_comment = - preprocessor->get_comment_before(pos.first_line, pos.file); - } - - _declarations.push_back(decl); - - handle_declaration(decl, global_scope, preprocessor); -} - -/** - * - */ -void CPPScope:: -add_enum_value(CPPInstance *inst) { - inst->_vis = _current_vis; - - string name = inst->get_simple_name(); - if (!name.empty()) { - _enum_values[name] = inst; - } -} - -/** - * - */ -void CPPScope:: -define_typedef_type(CPPTypedefType *type, CPPPreprocessor *error_sink) { - string name = type->get_simple_name(); - - pair result = - _types.insert(Types::value_type(name, type)); - - if (!result.second) { - CPPType *other_type = result.first->second; - CPPTypedefType *other_td = other_type->as_typedef_type(); - - // We don't do redefinitions of typedefs. But we don't complain as long - // as this is actually a typedef to the previous definition. - if (other_type != type->_type && - (other_td == nullptr || !other_td->_type->is_equivalent(*type->_type))) { - - if (error_sink != nullptr) { - ostringstream errstr; - type->output(errstr, 0, nullptr, false); - errstr << " has conflicting declaration as "; - other_type->output(errstr, 0, nullptr, true); - error_sink->error(errstr.str(), type->_ident->_loc); - if (other_td != nullptr && other_td->_ident != nullptr) { - error_sink->error("previous definition is here", - other_td->_ident->_loc); - } - } - } - } else { - _types[name] = type; - } - - // This might be a templated "using" definition. - if (type->is_template()) { - CPPTemplateScope *scope = type->get_template_scope(); - if (scope->_parameters._parameters.size() == 0) { - return; - } - - string simple_name = type->get_simple_name(); - - pair result = - _templates.insert(Templates::value_type(simple_name, type)); - - if (!result.second) { - // The template was not inserted because we already had a template - // definition with the given name. If the previous definition was - // incomplete, replace it. - CPPDeclaration *old_templ = (*result.first).second; - CPPType *old_templ_type = old_templ->as_type(); - if (old_templ_type == nullptr || old_templ_type->is_incomplete()) { - // The previous template definition was incomplete, maybe a forward - // reference; replace it with the good one. - (*result.first).second = type; - } - } - } -} - -/** - * - */ -void CPPScope:: -define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) { - assert(type != nullptr); - string name = type->get_local_name(this); - if (name.empty()) { - return; - } - - switch (type->_type) { - case CPPExtensionType::T_class: - _classes[name] = type; - break; - - case CPPExtensionType::T_struct: - _structs[name] = type; - break; - - case CPPExtensionType::T_union: - _unions[name] = type; - break; - - case CPPExtensionType::T_enum: - case CPPExtensionType::T_enum_struct: - case CPPExtensionType::T_enum_class: - _enums[name] = type; - break; - } - - // Create an implicit typedef for the extension. CPPTypedefType *td = new - // CPPTypedefType(type, name); - pair result = - _types.insert(Types::value_type(name, type)); - - if (!result.second) { - // There's already a typedef for this extension. This one overrides it - // only if the other is a forward declaration. - CPPType *other_type = (*result.first).second; - - if (other_type->get_subtype() == CPPDeclaration::ST_extension) { - CPPExtensionType *other_ext = other_type->as_extension_type(); - - if (other_ext->_type != type->_type) { - if (error_sink != nullptr) { - ostringstream errstr; - errstr << type->_type << " " << type->get_fully_scoped_name() - << " was previously declared as " << other_ext->_type; - error_sink->error(errstr.str(), type->_ident->_loc); - - if (other_ext->_ident != nullptr) { - error_sink->error("previous declaration is here", - other_ext->_ident->_loc); - } - } - } - (*result.first).second = type; - - } else { - CPPTypedefType *other_td = other_type->as_typedef_type(); - - // Error out if the declaration is different than the previous one. - if (other_type != type && - (other_td == nullptr || other_td->_type != type)) { - - if (error_sink != nullptr) { - ostringstream errstr; - if (!cppparser_output_class_keyword) { - errstr << type->_type << " "; - } - type->output(errstr, 0, nullptr, false); - errstr << " has conflicting definition as "; - other_type->output(errstr, 0, nullptr, true); - error_sink->error(errstr.str(), type->_ident->_loc); - - CPPExtensionType *other_ext = other_type->as_extension_type(); - if (other_ext != nullptr && other_ext->_ident != nullptr) { - error_sink->error("previous definition is here", - other_ext->_ident->_loc); - } - } - } - } - } - - if (type->is_template()) { - CPPTemplateScope *scope = type->get_template_scope(); - if (scope->_parameters._parameters.size() == 0) { - return; - } - - string simple_name = type->get_simple_name(); - - pair result = - _templates.insert(Templates::value_type(simple_name, type)); - - if (!result.second) { - // The template was not inserted because we already had a template - // definition with the given name. If the previous definition was - // incomplete, replace it. - CPPDeclaration *old_templ = (*result.first).second; - CPPType *old_templ_type = old_templ->as_type(); - if (old_templ_type == nullptr || old_templ_type->is_incomplete()) { - // The previous template definition was incomplete, maybe a forward - // reference; replace it with the good one. - (*result.first).second = type; - } - } - } -} - -/** - * - */ -void CPPScope:: -define_namespace(CPPNamespace *ns) { - string name = ns->get_simple_name(); - - _namespaces[name] = ns; - - if (ns->_is_inline) { - // Add an implicit using declaration for an inline namespace. - _using.insert(ns->get_scope()); - } -} - -/** - * - */ -void CPPScope:: -add_using(CPPUsing *using_decl, CPPScope *global_scope, - CPPPreprocessor *error_sink) { - if (using_decl->_full_namespace) { - CPPScope *scope = - using_decl->_ident->find_scope(this, global_scope); - if (scope != nullptr) { - _using.insert(scope); - } else { - if (error_sink != nullptr) { - error_sink->warning("Attempt to use undefined namespace: " + using_decl->_ident->get_fully_scoped_name(), using_decl->_ident->_loc); - } - } - } else { - CPPDeclaration *decl = using_decl->_ident->find_symbol(this, global_scope); - if (decl != nullptr) { - handle_declaration(decl, global_scope, error_sink); - } else { - if (error_sink != nullptr) { - error_sink->warning("Attempt to use unknown symbol: " + using_decl->_ident->get_fully_scoped_name(), using_decl->_ident->_loc); - } - } - } -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPScope:: -is_fully_specified() const { - if (_fully_specified_known) { - return _is_fully_specified; - } - - if (_is_fully_specified_recursive_protect) { - // We're already executing this block. - return true; - } - ((CPPScope *)this)->_is_fully_specified_recursive_protect = true; - - bool specified = true; - - if (_parent_scope != nullptr && !_parent_scope->is_fully_specified()) { - specified = false; - } - - Declarations::const_iterator di; - for (di = _declarations.begin(); - di != _declarations.end() && specified; - ++di) { - if (!(*di)->is_fully_specified()) { - specified = false; - } - } - - ((CPPScope *)this)->_fully_specified_known = true; - ((CPPScope *)this)->_is_fully_specified = specified; - ((CPPScope *)this)->_is_fully_specified_recursive_protect = false; - - return specified; -} - -/** - * - */ -CPPScope *CPPScope:: -instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - CPPScope *this_scope = (CPPScope *)this; - - if (_parent_scope == nullptr || - _parent_scope->as_template_scope() == nullptr) { - if (error_sink != nullptr) { - error_sink->warning("Ignoring template parameters for scope " + - get_local_name()); - } - return this_scope; - } - - if (is_fully_specified()) { - return this_scope; - } - - Instantiations::const_iterator ii; - ii = _instantiations.find(actual_params); - if (ii != _instantiations.end()) { - // We've already instantiated this scope with these parameters. Return - // that. - return (*ii).second; - } - - /* - cerr << "Instantiating " << get_simple_name() - << "<" << *actual_params << ">\n"; - */ - - // Build the mapping of formal parameters to actual parameters. - CPPTemplateScope *tscope = _parent_scope->as_template_scope(); - CPPDeclaration::SubstDecl subst; - actual_params->build_subst_decl(tscope->_parameters, subst, - current_scope, global_scope); - - CPPScope *scope; - if (subst.empty()) { - scope = (CPPScope *)this; - - } else { - CPPNameComponent name = _name; - name.set_templ(new CPPTemplateParameterList(*actual_params)); - // scope = new CPPScope(current_scope, name, V_public); - scope = new CPPScope(_parent_scope, name, V_public); - copy_substitute_decl(scope, subst, global_scope); - - // Also define any new template parameter types, in case we "instantiated" - // this scope with another template parameter. - CPPTemplateParameterList::Parameters::const_iterator pi; - for (pi = actual_params->_parameters.begin(); - pi != actual_params->_parameters.end(); - ++pi) { - CPPDeclaration *decl = (*pi); - CPPClassTemplateParameter *ctp = decl->as_class_template_parameter(); - if (ctp != nullptr) { - // CPPTypedefType *td = new CPPTypedefType(ctp, ctp->_ident); - // scope->_typedefs.insert(Typedefs::value_type - // (ctp->_ident->get_local_name(), td)); - scope->_types.insert(Types::value_type - (ctp->_ident->get_local_name(), - ctp)); - } - } - } - - // Finally, record this particular instantiation for future reference, so we - // don't have to do this again. - ((CPPScope *)this)->_instantiations.insert(Instantiations::value_type(actual_params, scope)); - - return scope; -} - -/** - * - */ -CPPScope *CPPScope:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) const { - CPPScope *this_scope = (CPPScope *)this; - - if (is_fully_specified()) { - return this_scope; - } - - if (_subst_decl_recursive_protect) { - // We're already executing this block. - return this_scope; - } - ((CPPScope *)this)->_subst_decl_recursive_protect = true; - - CPPScope *rep = new CPPScope(current_scope, _name, V_public); - bool anything_changed; - - if (_parent_scope != nullptr && - _parent_scope->as_template_scope() != nullptr) { - // If the parent of this scope is a template scope--e.g. this scope has - // template parameters--then we must first remove any of the template - // parameters from the subst list. These will later get substituted - // properly during instantiation. - const CPPTemplateParameterList &p = - _parent_scope->as_template_scope()->_parameters; - - CPPDeclaration::SubstDecl new_subst = subst; - CPPTemplateParameterList::Parameters::const_iterator pi; - for (pi = p._parameters.begin(); pi != p._parameters.end(); ++pi) { - new_subst.erase(*pi); - } - anything_changed = copy_substitute_decl(rep, new_subst, global_scope); - } else { - anything_changed = copy_substitute_decl(rep, subst, global_scope); - } - - if (!anything_changed && rep->_parent_scope == _parent_scope) { - delete rep; - rep = (CPPScope *)this; - } - ((CPPScope *)this)->_subst_decl_recursive_protect = false; - - return rep; -} - -/** - * - */ -CPPType *CPPScope:: -find_type(const string &name, bool recurse) const { - Types::const_iterator ti; - ti = _types.find(name); - if (ti != _types.end()) { - return ti->second; - } - - Using::const_iterator ui; - for (ui = _using.begin(); ui != _using.end(); ++ui) { - CPPType *type = (*ui)->find_type(name, false); - if (type != nullptr) { - return type; - } - } - - if (_struct_type != nullptr) { - CPPStructType::Derivation::const_iterator di; - for (di = _struct_type->_derivation.begin(); - di != _struct_type->_derivation.end(); - ++di) { - CPPStructType *st = (*di)._base->as_struct_type(); - if (st != nullptr) { - CPPType *type = st->_scope->find_type(name, false); - if (type != nullptr) { - return type; - } - } - } - } - - if (recurse && _parent_scope != nullptr) { - return _parent_scope->find_type(name); - } - - return nullptr; -} - -/** - * - */ -CPPType *CPPScope:: -find_type(const string &name, CPPDeclaration::SubstDecl &subst, - CPPScope *global_scope, bool recurse) const { - Types::const_iterator ti; - ti = _types.find(name); - if (ti != _types.end()) { - CPPScope *current_scope = (CPPScope *)this; - return (*ti).second->substitute_decl - (subst, current_scope, global_scope)->as_type(); - } - - Using::const_iterator ui; - for (ui = _using.begin(); ui != _using.end(); ++ui) { - CPPType *type = (*ui)->find_type(name, subst, global_scope, false); - if (type != nullptr) { - return type; - } - } - - if (_struct_type != nullptr) { - CPPStructType::Derivation::const_iterator di; - for (di = _struct_type->_derivation.begin(); - di != _struct_type->_derivation.end(); - ++di) { - CPPStructType *st = (*di)._base->as_struct_type(); - if (st != nullptr) { - CPPType *type = st->_scope->find_type(name, subst, global_scope, - false); - if (type != nullptr) { - return type; - } - } - } - } - - if (recurse && _parent_scope != nullptr) { - return _parent_scope->find_type(name, subst, global_scope); - } - - return nullptr; -} - -/** - * - */ -CPPScope *CPPScope:: -find_scope(const string &name, CPPScope *global_scope, bool recurse) const { - Namespaces::const_iterator ni = _namespaces.find(name); - if (ni != _namespaces.end()) { - return (*ni).second->get_scope(); - } - - CPPType *type = nullptr; - - Types::const_iterator ti; - ti = _types.find(name); - if (ti != _types.end()) { - type = (*ti).second; - // Resolve if this is a typedef or const, or a TBD type. - while (type->get_subtype() == CPPDeclaration::ST_const || - type->get_subtype() == CPPDeclaration::ST_typedef || - type->get_subtype() == CPPDeclaration::ST_tbd) { - if (type->as_typedef_type() != nullptr) { - type = type->as_typedef_type()->_type; - } else if (type->as_const_type() != nullptr) { - type = type->as_const_type()->_wrapped_around; - } else { - CPPType *new_type = type->resolve_type((CPPScope *)this, global_scope); - if (new_type != type) { - type = new_type; - } else { - break; - } - } - } - - } else if (_struct_type != nullptr) { - CPPStructType::Derivation::const_iterator di; - for (di = _struct_type->_derivation.begin(); - di != _struct_type->_derivation.end(); - ++di) { - CPPStructType *st = (*di)._base->as_struct_type(); - if (st != nullptr) { - type = st->_scope->find_type(name, false); - } - } - } - - if (type != nullptr) { - CPPStructType *st = type->as_struct_type(); - if (st != nullptr) { - return st->_scope; - } - - CPPEnumType *et = type->as_enum_type(); - if (et != nullptr) { - return et->_scope; - } - } - - Using::const_iterator ui; - for (ui = _using.begin(); ui != _using.end(); ++ui) { - CPPScope *scope = (*ui)->find_scope(name, global_scope, false); - if (scope != nullptr) { - return scope; - } - } - - if (recurse && _parent_scope != nullptr) { - return _parent_scope->find_scope(name, global_scope); - } - - return nullptr; -} - -/** - * - */ -CPPScope *CPPScope:: -find_scope(const string &name, CPPDeclaration::SubstDecl &subst, - CPPScope *global_scope, bool recurse) const { - CPPType *type = find_type(name, subst, global_scope, recurse); - if (type == nullptr) { - return nullptr; - } - - // Resolve if this is a typedef or const. - while (type->get_subtype() == CPPDeclaration::ST_const || - type->get_subtype() == CPPDeclaration::ST_typedef) { - if (type->as_typedef_type() != nullptr) { - type = type->as_typedef_type()->_type; - } else { - type = type->as_const_type()->_wrapped_around; - } - } - - CPPStructType *st = type->as_struct_type(); - if (st != nullptr) { - return st->_scope; - } - - CPPEnumType *et = type->as_enum_type(); - if (et != nullptr) { - return et->_scope; - } - - return nullptr; -} - -/** - * - */ -CPPDeclaration *CPPScope:: -find_symbol(const string &name, bool recurse) const { - if (_struct_type != nullptr && name == get_simple_name()) { - return _struct_type; - } - - Functions::const_iterator fi; - fi = _functions.find(name); - if (fi != _functions.end()) { - return (*fi).second; - } - - Types::const_iterator ti; - ti = _types.find(name); - if (ti != _types.end()) { - return (*ti).second; - } - - Variables::const_iterator vi; - vi = _variables.find(name); - if (vi != _variables.end()) { - return (*vi).second; - } - - vi = _enum_values.find(name); - if (vi != _enum_values.end()) { - return (*vi).second; - } - - Using::const_iterator ui; - for (ui = _using.begin(); ui != _using.end(); ++ui) { - CPPDeclaration *decl = (*ui)->find_symbol(name, false); - if (decl != nullptr) { - return decl; - } - } - - if (_struct_type != nullptr) { - CPPStructType::Derivation::const_iterator di; - for (di = _struct_type->_derivation.begin(); - di != _struct_type->_derivation.end(); - ++di) { - CPPStructType *st = (*di)._base->as_struct_type(); - if (st != nullptr) { - CPPDeclaration *decl = st->_scope->find_symbol(name, false); - if (decl != nullptr) { - return decl; - } - } - } - } - - if (recurse && _parent_scope != nullptr) { - return _parent_scope->find_symbol(name); - } - - return nullptr; -} - -/** - * - */ -CPPDeclaration *CPPScope:: -find_template(const string &name, bool recurse) const { - Templates::const_iterator ti; - ti = _templates.find(name); - if (ti != _templates.end()) { - return (*ti).second; - } - - Using::const_iterator ui; - for (ui = _using.begin(); ui != _using.end(); ++ui) { - CPPDeclaration *decl = (*ui)->find_template(name, false); - if (decl != nullptr) { - return decl; - } - } - - if (_struct_type != nullptr) { - CPPStructType::Derivation::const_iterator di; - for (di = _struct_type->_derivation.begin(); - di != _struct_type->_derivation.end(); - ++di) { - CPPStructType *st = (*di)._base->as_struct_type(); - if (st != nullptr) { - CPPDeclaration *decl = st->_scope->find_template(name, false); - if (decl != nullptr) { - return decl; - } - } - } - } - - if (recurse && _parent_scope != nullptr) { - return _parent_scope->find_template(name); - } - - return nullptr; -} - -/** - * - */ -string CPPScope:: -get_simple_name() const { - /* - if (_struct_type != (CPPStructType *)NULL) { - return _struct_type->get_simple_name(); - } - */ - return _name.get_name(); -} - -/** - * - */ -string CPPScope:: -get_local_name(CPPScope *scope) const { - /* - if (_struct_type != (CPPStructType *)NULL) { - return _struct_type->get_local_name(scope); - } - */ - - if (scope != nullptr && _parent_scope != nullptr/* && _parent_scope != scope*/) { - string parent_scope_name = _parent_scope->get_local_name(scope); - if (parent_scope_name.empty()) { - return _name.get_name_with_templ(); - } else { - return parent_scope_name + "::" + - _name.get_name_with_templ(); - } - } else { - return _name.get_name_with_templ(); - } -} - -/** - * - */ -string CPPScope:: -get_fully_scoped_name() const { - /* - if (_struct_type != (CPPStructType *)NULL) { - return _struct_type->get_fully_scoped_name(); - } - */ - - if (_parent_scope != nullptr) { - return _parent_scope->get_fully_scoped_name() + "::" + - _name.get_name_with_templ(); - } else { - return _name.get_name_with_templ(); - } -} - -/** - * - */ -void CPPScope:: -output(ostream &out, CPPScope *scope) const { - // out << get_local_name(scope); - if (_parent_scope != nullptr && _parent_scope != scope) { - _parent_scope->output(out, scope); - out << "::"; - } - out << _name; -} - -/** - * - */ -void CPPScope:: -write(ostream &out, int indent_level, CPPScope *scope) const { - CPPVisibility vis = V_unknown; - Declarations::const_iterator di; - for (di = _declarations.begin(); di != _declarations.end(); ++di) { - CPPDeclaration *cd = (*di); - if (cd->_vis != vis && indent_level > 0) { - vis = cd->_vis; - indent(out, indent_level - 2) << vis << ":\n"; - } - bool complete = false; - - if (cd->as_type() != nullptr || cd->as_namespace() != nullptr) { - complete = true; - } - - indent(out, indent_level); - cd->output(out, indent_level, scope, complete); - out << ";\n"; - } -} - -/** - * Returns the nearest ancestor of this scope that is a template scope, or - * NULL if the scope is fully specified. - */ -CPPTemplateScope *CPPScope:: -get_template_scope() { - if (as_template_scope()) { - return as_template_scope(); - } - if (_parent_scope != nullptr) { - return _parent_scope->get_template_scope(); - } - return nullptr; -} - -/** - * - */ -CPPTemplateScope *CPPScope:: -as_template_scope() { - return nullptr; -} - -/** - * This is in support of both substitute_decl() and instantiate(). It's - * similar in purpose to substitute_decl(), but this function assumes the - * caller has already created a new, empty scope. All of the declarations in - * this scope are copied to the new scope, filtering through the subst decl. - * - * The return value is true if the scope is changed, false if it is not. - */ -bool CPPScope:: -copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst, - CPPScope *global_scope) const { - bool anything_changed = false; - - if (_struct_type != nullptr) { - CPPScope *native_scope = nullptr; - if (_struct_type->_ident != nullptr) { - native_scope = _struct_type->_ident->_native_scope; - } - to_scope->_struct_type = - new CPPStructType(_struct_type->_type, - new CPPIdentifier(to_scope->_name, _struct_type->_file), - native_scope, to_scope, _struct_type->_file); - to_scope->_struct_type->_incomplete = false; - - // Copy the derivation to the new type. - CPPStructType::Derivation::const_iterator di; - for (di = _struct_type->_derivation.begin(); - di != _struct_type->_derivation.end(); - ++di) { - CPPStructType::Base b = (*di); - b._base = - (*di)._base->substitute_decl(subst, to_scope, global_scope)->as_type(); - to_scope->_struct_type->_derivation.push_back(b); - if (b._base != (*di)._base) { - anything_changed = true; - } - } - } - - Declarations::const_iterator di; - for (di = _declarations.begin(); di != _declarations.end(); ++di) { - CPPDeclaration *decl = - (*di)->substitute_decl(subst, to_scope, global_scope); - to_scope->_declarations.push_back(decl); - if (decl != (*di)) { - anything_changed = true; - } - } - - ExtensionTypes::const_iterator ei; - for (ei = _structs.begin(); ei != _structs.end(); ++ei) { - string name = (*ei).first; - CPPType *source_type = (*ei).second; - CPPDeclaration *decl = - source_type->substitute_decl(subst, to_scope, global_scope); - assert(decl != nullptr); - CPPType *new_type = decl->as_type(); - assert(new_type != nullptr); - to_scope->_structs.insert(ExtensionTypes::value_type(name, new_type)); - if (new_type != source_type) { - anything_changed = true; - } - } - for (ei = _classes.begin(); ei != _classes.end(); ++ei) { - string name = (*ei).first; - CPPType *source_type = (*ei).second; - CPPDeclaration *decl = - source_type->substitute_decl(subst, to_scope, global_scope); - assert(decl != nullptr); - CPPType *new_type = decl->as_type(); - assert(new_type != nullptr); - to_scope->_classes.insert(ExtensionTypes::value_type(name, new_type)); - if (new_type != source_type) { - anything_changed = true; - } - } - for (ei = _unions.begin(); ei != _unions.end(); ++ei) { - string name = (*ei).first; - CPPType *source_type = (*ei).second; - CPPDeclaration *decl = - source_type->substitute_decl(subst, to_scope, global_scope); - assert(decl != nullptr); - CPPType *new_type = decl->as_type(); - assert(new_type != nullptr); - to_scope->_unions.insert(ExtensionTypes::value_type(name, new_type)); - if (new_type != source_type) { - anything_changed = true; - } - } - for (ei = _enums.begin(); ei != _enums.end(); ++ei) { - string name = (*ei).first; - CPPType *source_type = (*ei).second; - CPPDeclaration *decl = - source_type->substitute_decl(subst, to_scope, global_scope); - assert(decl != nullptr); - CPPType *new_type = decl->as_type(); - assert(new_type != nullptr); - to_scope->_enums.insert(ExtensionTypes::value_type(name, new_type)); - if (new_type != source_type) { - anything_changed = true; - } - } - Functions::const_iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - string name = fgroup->_name; - - CPPFunctionGroup *&to_fgroup = to_scope->_functions[name]; - if (to_fgroup == nullptr) { - to_fgroup = new CPPFunctionGroup(name); - } - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = - (*ii)->substitute_decl(subst, to_scope, global_scope)->as_instance(); - to_fgroup->_instances.push_back(inst); - if (inst != (*ii)) { - anything_changed = true; - } - } - } - - Types::const_iterator ti; - for (ti = _types.begin(); ti != _types.end(); ++ti) { - CPPType *td = - (*ti).second->substitute_decl(subst, to_scope, global_scope)->as_type(); - to_scope->_types.insert(Types::value_type((*ti).first, td)); - if (td != (*ti).second) { - anything_changed = true; - } - } - Variables::const_iterator vi; - for (vi = _variables.begin(); vi != _variables.end(); ++vi) { - CPPInstance *inst = - (*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance(); - to_scope->_variables.insert(Variables::value_type((*vi).first, inst)); - if (inst != (*vi).second) { - anything_changed = true; - } - } - - for (vi = _enum_values.begin(); vi != _enum_values.end(); ++vi) { - CPPInstance *inst = - (*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance(); - to_scope->_enum_values.insert(Variables::value_type((*vi).first, inst)); - if (inst != (*vi).second) { - anything_changed = true; - } - } - - Templates::const_iterator tmi; - for (tmi = _templates.begin(); tmi != _templates.end(); ++tmi) { - CPPDeclaration *decl = - (*tmi).second->substitute_decl(subst, to_scope, global_scope); - to_scope->_templates.insert(Templates::value_type((*tmi).first, decl)); - if (decl != (*tmi).second) { - anything_changed = true; - } - } - - return anything_changed; -} - - -/** - * Does the right thing with a newly given declaration: adds it to the typedef - * list, or variables or functions, or whatever. - */ -void CPPScope:: -handle_declaration(CPPDeclaration *decl, CPPScope *global_scope, - CPPPreprocessor *error_sink) { - CPPTypedefType *def = decl->as_typedef_type(); - if (def != nullptr) { - define_typedef_type(def, error_sink); - - CPPExtensionType *et = def->_type->as_extension_type(); - if (et != nullptr) { - define_extension_type(et, error_sink); - } - return; - } - - CPPTypeDeclaration *typedecl = decl->as_type_declaration(); - if (typedecl != nullptr) { - CPPExtensionType *et = typedecl->_type->as_extension_type(); - if (et != nullptr) { - define_extension_type(et, error_sink); - } - return; - } - - CPPInstance *inst = decl->as_instance(); - if (inst != nullptr) { - inst->check_for_constructor(this, global_scope); - - if (inst->_ident != nullptr) { - // Not sure if this is the best place to assign this. However, this - // fixes a bug with variables in expressions not having the proper - // scoping prefix. ~rdb - inst->_ident->_native_scope = this; - } - - string name = inst->get_simple_name(); - if (!name.empty() && inst->get_scope(this, global_scope) == this) { - if (inst->_type->as_function_type()) { - // This is a function declaration; hence it gets added to the - // _functions member. But we must be careful to share common-named - // functions. - - CPPFunctionGroup *fgroup; - Functions::const_iterator fi; - fi = _functions.find(name); - if (fi == _functions.end()) { - fgroup = new CPPFunctionGroup(name); - _functions.insert(Functions::value_type(name, fgroup)); - } else { - fgroup = (*fi).second; - } - fgroup->_instances.push_back(inst); - - } else { - // This is not a function declaration; hence it gets added to the - // _variables member. - _variables[name] = inst; - } - - if (inst->is_template()) { - // Don't add a new template definition if we already had one by the - // same name in another scope. - - if (find_template(name) == nullptr) { - _templates.insert(Templates::value_type(name, inst)); - } - - /* - if (inst->_type->as_function_type() == NULL || - (inst->_type->as_function_type()->_flags & - CPPFunctionType::F_constructor) == 0) { - _templates.insert(Templates::value_type(name, inst)); - } - */ - } - } - return; - } - - CPPExtensionType *et = decl->as_extension_type(); - if (et != nullptr) { - define_extension_type(et, error_sink); - } -} diff --git a/dtool/src/cppparser/cppScope.h b/dtool/src/cppparser/cppScope.h deleted file mode 100644 index 2631d6097a..0000000000 --- a/dtool/src/cppparser/cppScope.h +++ /dev/null @@ -1,165 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppScope.h - * @author drose - * @date 1999-10-21 - */ - -#ifndef CPPSCOPE_H -#define CPPSCOPE_H - -#include "dtoolbase.h" - -#include "cppVisibility.h" -#include "cppTemplateParameterList.h" -#include "cppNameComponent.h" - -#include -#include -#include -#include - -class CPPType; -class CPPDeclaration; -class CPPExtensionType; -class CPPStructType; -class CPPNamespace; -class CPPUsing; -class CPPTypedefType; -class CPPInstance; -class CPPFunctionGroup; -class CPPTemplateScope; -class CPPTemplateParameterList; -class CPPPreprocessor; -class CPPNameComponent; -struct cppyyltype; - -/** - * - */ -class CPPScope { -public: - CPPScope(CPPScope *parent_scope, - const CPPNameComponent &name, CPPVisibility starting_vis); - virtual ~CPPScope(); - - void set_current_vis(CPPVisibility current_vis); - CPPVisibility get_current_vis() const; - - void set_struct_type(CPPStructType *struct_type); - CPPStructType *get_struct_type() const; - CPPScope *get_parent_scope() const; - - virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope, - CPPPreprocessor *preprocessor, - const cppyyltype &pos); - virtual void add_enum_value(CPPInstance *inst); - virtual void define_typedef_type(CPPTypedefType *type, - CPPPreprocessor *error_sink = nullptr); - virtual void define_extension_type(CPPExtensionType *type, - CPPPreprocessor *error_sink = nullptr); - virtual void define_namespace(CPPNamespace *scope); - virtual void add_using(CPPUsing *using_decl, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr); - - virtual bool is_fully_specified() const; - - CPPScope * - instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - CPPScope * - substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope) const; - - CPPType *find_type(const std::string &name, bool recurse = true) const; - CPPType *find_type(const std::string &name, - CPPDeclaration::SubstDecl &subst, - CPPScope *global_scope, - bool recurse = true) const; - CPPScope *find_scope(const std::string &name, CPPScope *global_scope, - bool recurse = true) const; - CPPScope *find_scope(const std::string &name, - CPPDeclaration::SubstDecl &subst, - CPPScope *global_scope, - bool recurse = true) const; - CPPDeclaration *find_symbol(const std::string &name, - bool recurse = true) const; - CPPDeclaration *find_template(const std::string &name, - bool recurse = true) const; - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual void output(std::ostream &out, CPPScope *scope) const; - void write(std::ostream &out, int indent, CPPScope *scope) const; - - CPPTemplateScope *get_template_scope(); - virtual CPPTemplateScope *as_template_scope(); - -private: - bool - copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst, - CPPScope *global_scope) const; - - void handle_declaration(CPPDeclaration *decl, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr); - -public: - typedef std::vector Declarations; - Declarations _declarations; - - typedef std::map ExtensionTypes; - ExtensionTypes _structs; - ExtensionTypes _classes; - ExtensionTypes _unions; - ExtensionTypes _enums; - - typedef std::map Namespaces; - Namespaces _namespaces; - - typedef std::map Types; - Types _types; - typedef std::map Variables; - Variables _variables; - Variables _enum_values; - typedef std::map Functions; - Functions _functions; - typedef std::map Templates; - Templates _templates; - CPPNameComponent _name; - - typedef std::set Using; - Using _using; - -protected: - CPPScope *_parent_scope; - CPPStructType *_struct_type; - CPPVisibility _current_vis; - -private: - typedef std::map Instantiations; - Instantiations _instantiations; - - bool _is_fully_specified; - bool _fully_specified_known; - bool _is_fully_specified_recursive_protect; - bool _subst_decl_recursive_protect; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPScope &scope) { - scope.output(out, nullptr); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppSimpleType.cxx b/dtool/src/cppparser/cppSimpleType.cxx deleted file mode 100644 index 990a7cbaea..0000000000 --- a/dtool/src/cppparser/cppSimpleType.cxx +++ /dev/null @@ -1,288 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppSimpleType.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppSimpleType.h" -#include "cppGlobals.h" - -/** - * - */ -CPPSimpleType:: -CPPSimpleType(CPPSimpleType::Type type, int flags) : - CPPType(CPPFile()), - _type(type), _flags(flags) -{ -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPSimpleType:: -is_tbd() const { - return (_type == T_unknown); -} - -/** - * Returns true if the type is a boolean, floating point or integral type. - */ -bool CPPSimpleType:: -is_arithmetic() const { - return (_type > T_unknown && _type < T_void); -} - -/** - * Returns true if the type is considered a fundamental type. - */ -bool CPPSimpleType:: -is_fundamental() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPSimpleType:: -is_standard_layout() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPSimpleType:: -is_trivial() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPSimpleType:: -is_trivially_copyable() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPSimpleType:: -is_constructible(const CPPType *given_type) const { - given_type = ((CPPType *)given_type)->remove_reference()->remove_cv(); - - const CPPSimpleType *simple_type = given_type->as_simple_type(); - if (simple_type == nullptr) { - return given_type->is_enum() && is_arithmetic(); - } else if (_type == T_nullptr) { - return simple_type->_type == T_nullptr; - } else if (_type == T_bool) { - return simple_type->is_arithmetic() || simple_type->_type == T_nullptr; - } else if (is_arithmetic()) { - return simple_type->is_arithmetic(); - } else { - return false; - } -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPSimpleType:: -is_default_constructible() const { - return (_type != T_void); -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPSimpleType:: -is_copy_constructible() const { - return (_type != T_void); -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPSimpleType:: -is_copy_assignable() const { - return (_type != T_void); -} - -/** - * Returns true if the type is destructible. - */ -bool CPPSimpleType:: -is_destructible() const { - return (_type != T_void); -} - -/** - * Returns true if the type is a special parameter expression type. - * - * This sort of type is created to handle instance declarations that initially - * look like function prototypes. - */ -bool CPPSimpleType:: -is_parameter_expr() const { - return (_type == T_parameter); -} - -/** - * - */ -std::string CPPSimpleType:: -get_preferred_name() const { - // Simple types always prefer to use their native types. - return get_local_name(); -} - -/** - * - */ -void CPPSimpleType:: -output(std::ostream &out, int, CPPScope *, bool) const { - if (_flags & F_unsigned) { - out << "unsigned "; - } - - if (_flags & F_signed) { - out << "signed "; - } - - if ((_type == T_int && (_flags & F_longlong) != 0) && - !cpp_longlong_keyword.empty()) { - // It's a long long, and we have a specific long long type name. This is - // to output code for compilers that don't recognize "long long int". - out << cpp_longlong_keyword; - return; - } - - if (_flags & F_longlong) { - out << "long long "; - } else if (_flags & F_long) { - out << "long "; - } else if (_flags & F_short) { - out << "short "; - } - - switch (_type) { - case T_unknown: - out << "unknown"; - break; - - case T_bool: - out << "bool"; - break; - - case T_char: - out << "char"; - break; - - case T_wchar_t: - out << "wchar_t"; - break; - - case T_char8_t: - out << "char8_t"; - break; - - case T_char16_t: - out << "char16_t"; - break; - - case T_char32_t: - out << "char32_t"; - break; - - case T_int: - out << "int"; - break; - - case T_float: - out << "float"; - break; - - case T_double: - out << "double"; - break; - - case T_void: - out << "void"; - break; - - case T_nullptr: - out << "decltype(nullptr)"; - break; - - case T_parameter: - out << "parameter"; - break; - - case T_auto: - out << "auto"; - break; - - case T_va_list: - out << "__builtin_va_list"; - break; - - default: - out << "***invalid type***"; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPSimpleType:: -get_subtype() const { - return ST_simple; -} - -/** - * - */ -CPPSimpleType *CPPSimpleType:: -as_simple_type() { - return this; -} - - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPSimpleType:: -is_equal(const CPPDeclaration *other) const { - const CPPSimpleType *ot = ((CPPDeclaration *)other)->as_simple_type(); - assert(ot != nullptr); - - return _type == ot->_type && _flags == ot->_flags; -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPSimpleType:: -is_less(const CPPDeclaration *other) const { - const CPPSimpleType *ot = ((CPPDeclaration *)other)->as_simple_type(); - assert(ot != nullptr); - - if (_type != ot->_type) { - return _type < ot->_type; - } - return _flags < ot->_flags; -} diff --git a/dtool/src/cppparser/cppSimpleType.h b/dtool/src/cppparser/cppSimpleType.h deleted file mode 100644 index 70eb615588..0000000000 --- a/dtool/src/cppparser/cppSimpleType.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppSimpleType.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPSIMPLETYPE_H -#define CPPSIMPLETYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -/** - * Represents a C++ fundamental type. - */ -class CPPSimpleType : public CPPType { -public: - enum Type { - T_unknown, - T_bool, - T_char, - T_wchar_t, - T_char8_t, - T_char16_t, - T_char32_t, - T_int, - T_float, - T_double, - T_void, - - // We need something to represent the type of nullptr so that we can - // return it from decltype(nullptr). Note that this is not the same as - // nullptr_t, which is a typedef of decltype(nullptr). - T_nullptr, - - // T_parameter is a special type which is assigned to expressions that are - // discovered where a formal parameter was expected. This is a special - // case for handling cases like this: int foo(0); which really means the - // same thing as: int foo = 0; but it initially looks like a function - // prototype. - T_parameter, - - // T_auto is also a special type that corresponds to the "auto" keyword - // used in a variable assignment. The type of it is automatically - // determined at a later stage based on the type of the expression that is - // assigned to it. - T_auto, - - // This is also a special built-in type. - T_va_list, - }; - - enum Flags { - F_long = 0x001, - F_longlong = 0x002, - F_short = 0x004, - F_unsigned = 0x008, - F_signed = 0x010, - }; - - CPPSimpleType(Type type, int flags = 0); - - Type _type; - int _flags; - - virtual bool is_tbd() const; - bool is_arithmetic() const; - virtual bool is_fundamental() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - virtual bool is_destructible() const; - virtual bool is_parameter_expr() const; - - virtual std::string get_preferred_name() const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPSimpleType *as_simple_type(); - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; -}; - -#endif diff --git a/dtool/src/cppparser/cppStructType.cxx b/dtool/src/cppparser/cppStructType.cxx deleted file mode 100644 index b2ce921e70..0000000000 --- a/dtool/src/cppparser/cppStructType.cxx +++ /dev/null @@ -1,1546 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppStructType.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppStructType.h" -#include "cppTypedefType.h" -#include "cppReferenceType.h" -#include "cppScope.h" -#include "cppTypeProxy.h" -#include "cppTemplateScope.h" -#include "cppFunctionGroup.h" -#include "cppFunctionType.h" -#include "cppParameterList.h" -#include "cppTBDType.h" -#include "indent.h" -#include "cppParser.h" - -/** - * - */ -void CPPStructType::Base:: -output(std::ostream &out) const { - if (_is_virtual) { - out << "virtual "; - } - out << _vis << " " << *_base; -} - -/** - * - */ -CPPStructType:: -CPPStructType(CPPStructType::Type type, CPPIdentifier *ident, - CPPScope *current_scope, CPPScope *scope, - const CPPFile &file, CPPAttributeList attr) : - CPPExtensionType(type, ident, current_scope, file, std::move(attr)), - _scope(scope), - _final(false) -{ - _subst_decl_recursive_protect = false; - _incomplete = true; -} - -/** - * - */ -CPPStructType:: -CPPStructType(const CPPStructType ©) : - CPPExtensionType(copy), - _scope(copy._scope), - _incomplete(copy._incomplete), - _final(copy._final), - _derivation(copy._derivation) -{ - _subst_decl_recursive_protect = false; -} - -/** - * - */ -void CPPStructType:: -operator = (const CPPStructType ©) { - CPPExtensionType::operator = (copy); - _scope = copy._scope; - _incomplete = copy._incomplete; - _derivation = copy._derivation; - _final = copy._final; -} - -/** - * A handy function used while parsing to add a new base class to the list of - * classes (or structs) this class derives from. - */ -void CPPStructType:: -append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual) { - if (base != nullptr) { - // Unwrap any typedefs, since we can't inherit from a typedef. - CPPTypedefType *def = base->as_typedef_type(); - while (def != nullptr) { - base = def->_type; - def = base->as_typedef_type(); - } - - if (vis == V_unknown && base->as_extension_type() != nullptr) { - // Default visibility. - if (base->as_extension_type()->_type == T_class) { - vis = V_private; - } else { - vis = V_public; - } - } - - Base b; - b._base = base; - b._vis = vis; - b._is_virtual = is_virtual; - - _derivation.push_back(b); - } -} - -/** - * - */ -CPPScope *CPPStructType:: -get_scope() const { - return _scope; -} - -/** - * Returns true if this struct declaration is abstract, e.g. it contains or - * inherits at least one method that is pure virtual. - */ -bool CPPStructType:: -is_abstract() const { - VFunctions funcs; - get_pure_virtual_funcs(funcs); - return !funcs.empty(); -} - -/** - * Returns true if this struct declaration is a base class of the other given - * class, or the same class. - */ -bool CPPStructType:: -is_base_of(const CPPStructType *other) const { - if (this == other) { - return true; - } - Derivation::const_iterator di; - for (di = other->_derivation.begin(); di != other->_derivation.end(); ++di) { - const CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr && is_base_of(base)) { - return true; - } - } - return false; -} - -/** - * Returns true if this struct declaration defines no non-static data members - * other than bit-fields of size 0, no virtual functions, no virtual base - * classes, and no non-empty base classes, and is not a union. - */ -bool CPPStructType:: -is_empty() const { - if (_type == T_union) { - return false; - } - - if (check_virtual()) { - return false; - } - - // Make sure all base classes are empty and non-virtual. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if ((*di)._is_virtual || (base != nullptr && !base->is_empty())) { - return false; - } - } - - // Make sure there are no non-static data members. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - // Only members with a bit width of 0 are okay. - if (instance->_bit_width != 0) { - return false; - } - } - - return true; -} - -/** - * Returns true if this class or any of its base classes have virtual methods. - */ -bool CPPStructType:: -is_polymorphic() const { - if (_type == T_union) { - return false; - } - return check_virtual(); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPStructType:: -is_standard_layout() const { - assert(_scope != nullptr); - - CPPVisibility member_vis = V_unknown; - - // Make sure all data members have the same vis and are standard layout. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - // Finally, check if the data member itself is standard layout. - assert(instance->_type != nullptr); - if (!instance->_type->is_standard_layout()) { - return false; - } - - if (member_vis == V_unknown) { - // The first non-static data member may not be a base class. - CPPStructType *struct_type = instance->_type->remove_cv()->as_struct_type(); - if (struct_type != nullptr && struct_type->is_base_of(this)) { - return false; - } - member_vis = instance->_vis; - - } else if (member_vis != instance->_vis) { - // All members need to have the same access control. - return false; - } - } - - // Make sure all base classes are standard-layout and non-virtual. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if ((*di)._is_virtual) { - return false; - } - - // If this class had instance members, all base classes need to be empty. - if (member_vis != V_unknown) { - if (!base->is_empty()) { - return false; - } - } else { - if (!base->is_standard_layout()) { - return false; - } - } - } - - // Make sure we have no virtual functions. - return !check_virtual(); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPStructType:: -is_trivial() const { - // Make sure all base classes are trivial and non-virtual. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if ((*di)._is_virtual || (base != nullptr && !base->is_trivial())) { - return false; - } - } - - assert(_scope != nullptr); - - // Make sure all members are trivial. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - if (instance->_initializer != nullptr) { - // A member with an initializer means the default constructor would - // assign a value. This means the type can't be trivial. - return false; - } - - // Finally, check if the data member itself is non-trivial. - assert(instance->_type != nullptr); - if (!instance->_type->is_trivial()) { - return false; - } - } - - // Now look for functions that are virtual or con/destructors. - CPPScope::Functions::const_iterator fi; - for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) { - CPPInstance *inst = (*ii); - - if (inst->_storage_class & CPPInstance::SC_virtual) { - // Virtual functions are banned right off the bat. - return false; - } - - // The following checks don't apply for defaulted functions. - if (inst->_storage_class & CPPInstance::SC_defaulted) { - continue; - } - - assert(inst->_type != nullptr); - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if (ftype->_flags & (CPPFunctionType::F_destructor | - CPPFunctionType::F_move_constructor | - CPPFunctionType::F_copy_constructor)) { - // User-provided destructors and copy/move constructors are not - // trivial unless they are defaulted (and not virtual). - return false; - } - - if ((ftype->_flags & CPPFunctionType::F_constructor) != 0) { - if (ftype->_parameters->_parameters.size() == 0 && - !ftype->_parameters->_includes_ellipsis) { - // Same for the default constructor. - return false; - } - } - - if (fgroup->_name == "operator =") { - // Or assignment operators. - return false; - } - } - } - - // Finally, the class must be default-constructible. - return is_default_constructible(V_public); -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPStructType:: -is_trivially_copyable() const { - // Make sure all base classes are trivially copyable and non-virtual. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if ((*di)._is_virtual || (base != nullptr && !base->is_trivially_copyable())) { - return false; - } - } - - assert(_scope != nullptr); - - // Make sure all members are trivially copyable. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - assert(instance->_type != nullptr); - if (!instance->_type->is_trivially_copyable()) { - return false; - } - } - - // Now look for functions that are virtual or con/destructors. - CPPScope::Functions::const_iterator fi; - for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) { - CPPInstance *inst = (*ii); - - if (inst->_storage_class & CPPInstance::SC_virtual) { - // Virtual functions are banned right off the bat. - return false; - } - - // The following checks don't apply for defaulted functions. - if (inst->_storage_class & CPPInstance::SC_defaulted) { - continue; - } - - assert(inst->_type != nullptr); - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if (ftype->_flags & (CPPFunctionType::F_destructor | - CPPFunctionType::F_move_constructor | - CPPFunctionType::F_copy_constructor)) { - // User-provided destructors and copy/move constructors are not - // trivial unless they are defaulted (and not virtual). - return false; - } - - if (fgroup->_name == "operator =") { - // Or assignment operators. - return false; - } - } - } - - return true; -} - -/** - * Returns true if the type can be constructed using the given argument. - * This implementation is rudimentary, as it does not attempt to follow all of - * the implicit type conversion rules, but it is still useful. - */ -bool CPPStructType:: -is_constructible(const CPPType *given_type) const { - // Does the type match the copy constructor or move constructor? - CPPType *base_type = ((CPPType *)given_type)->remove_reference(); - if (is_equivalent(*base_type->remove_cv())) { - const CPPReferenceType *ref_type = given_type->as_reference_type(); - if (ref_type == nullptr || - ref_type->_value_category == CPPReferenceType::VC_rvalue) { - return is_move_constructible(V_public); - } else { - return is_copy_constructible(V_public); - } - } - - if (is_abstract()) { - return false; - } - - // Check for a different constructor. - CPPFunctionGroup *fgroup = get_constructor(); - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - CPPParameterList *params = ftype->_parameters; - if (params->_parameters.size() == 1 && !params->_includes_ellipsis) { - CPPType *param_type = params->_parameters[0]->_type->remove_reference(); - - if (!param_type->is_const() && base_type->is_const()) { - // Can't pass a const object to a function taking a non-const. - continue; - } - - // It's deleted, anyhow. - if ((inst->_storage_class & CPPInstance::SC_deleted) != 0) { - continue; - } - - if (param_type->is_equivalent(*base_type)) { - return true; - } - } - } - } - - return false; -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPStructType:: -is_default_constructible() const { - return is_default_constructible(V_public); -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPStructType:: -is_copy_constructible() const { - return is_copy_constructible(V_public); -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPStructType:: -is_copy_assignable() const { - if (is_abstract()) { - return false; - } - return is_copy_assignable(V_public); -} - -/** - * Returns true if the type is destructible. - */ -bool CPPStructType:: -is_destructible() const { - return is_destructible(V_public); -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPStructType:: -is_default_constructible(CPPVisibility min_vis) const { - if (is_abstract()) { - return false; - } - - CPPInstance *constructor = get_default_constructor(); - if (constructor != nullptr) { - // It has a default constructor. - if (constructor->_vis > min_vis) { - // Inaccessible default constructor. - return false; - } - - if (constructor->_storage_class & CPPInstance::SC_deleted) { - // Deleted default constructor. - return false; - } - - return true; - } - - // Does it have constructors at all? If so, no implicit one is generated. - if (get_constructor() != nullptr) { - return false; - } - - // Implicit default constructor. Check if the implicit default constructor - // is deleted. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr) { - if (!base->is_default_constructible(V_protected)) { - return false; - } - } - } - - // Make sure all members are default-constructible or have default values. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - if (instance->_initializer != nullptr) { - // It has a default value. - continue; - } - - if (!instance->_type->is_default_constructible()) { - return false; - } - } - - return true; -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPStructType:: -is_copy_constructible(CPPVisibility min_vis) const { - if (is_abstract()) { - return false; - } - - CPPInstance *constructor = get_copy_constructor(); - if (constructor != nullptr) { - // It has a copy constructor. - if (constructor->_vis > min_vis) { - // Inaccessible copy constructor. - return false; - } - - if (constructor->_storage_class & CPPInstance::SC_deleted) { - // Deleted copy constructor. - return false; - } - - return true; - } - - if (get_move_constructor() != nullptr || - get_move_assignment_operator() != nullptr) { - // A user-declared move constructor or move assignment operator means that - // the implicitly-declared copy constructor is deleted. - return false; - } - - CPPInstance *destructor = get_destructor(); - if (destructor != nullptr) { - if (destructor->_vis > min_vis) { - // Inaccessible destructor. - return false; - } - - if (destructor->_storage_class & CPPInstance::SC_deleted) { - // Deleted destructor. - return false; - } - } - - // Implicit copy constructor. Check if the implicit copy constructor is - // deleted. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr) { - if (!base->is_copy_constructible(V_protected)) { - return false; - } - } - } - - // Make sure all members are copy-constructible. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - if (!instance->_type->is_copy_constructible()) { - return false; - } - } - - return true; -} - -/** - * Returns true if the type is move-constructible. - */ -bool CPPStructType:: -is_move_constructible(CPPVisibility min_vis) const { - CPPInstance *constructor = get_move_constructor(); - if (constructor != nullptr) { - // It has a user-declared move constructor. - if (constructor->_vis > min_vis) { - // Inaccessible move constructor. - return false; - } - - if (constructor->_storage_class & CPPInstance::SC_deleted) { - // It is deleted. - return false; - } - - if (is_abstract()) { - return false; - } - - return true; - } - - return is_copy_constructible(min_vis); -} - -/** - * Returns true if the type is copy-assignable, without checking whether the - * class is abstract. - */ -bool CPPStructType:: -is_copy_assignable(CPPVisibility min_vis) const { - CPPInstance *assignment_operator = get_copy_assignment_operator(); - if (assignment_operator != nullptr) { - // It has a copy assignment operator. - if (assignment_operator->_vis > min_vis) { - // Inaccessible copy assignment operator. - return false; - } - - if (assignment_operator->_storage_class & CPPInstance::SC_deleted) { - // Deleted copy assignment operator. - return false; - } - - // NB: if it's defaulted, it may still be deleted. - if ((assignment_operator->_storage_class & CPPInstance::SC_defaulted) == 0) { - return true; - } - } - - // Implicit copy assignment operator. Check if the implicit or defaulted - // copy assignment operator is deleted. - if (!assignment_operator && (get_move_constructor() || get_move_assignment_operator())) { - // It's not explicitly defaulted, and there is a move constructor or move - // assignment operator, so the implicitly-declared one is deleted. - return false; - } - - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr) { - if (!base->is_copy_assignable(V_protected)) { - return false; - } - } - } - - // Make sure all members are assignable. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - if (!instance->_type->is_copy_assignable()) { - // Const or reference member, can't do it. - return false; - } - } - - return true; -} - -/** - * Returns true if the type is move-assignable. - */ -bool CPPStructType:: -is_move_assignable(CPPVisibility min_vis) const { - CPPInstance *assignment_operator = get_move_assignment_operator(); - if (assignment_operator != nullptr) { - // It has a user-declared move assignment_operator. - if (assignment_operator->_vis > min_vis) { - // Inaccessible move assignment_operator. - return false; - } - - if (assignment_operator->_storage_class & CPPInstance::SC_deleted) { - // It is deleted. - return false; - } - - if (is_abstract()) { - return false; - } - - return true; - } - - return is_copy_assignable(min_vis); -} - -/** - * Returns true if the type is destructible. - */ -bool CPPStructType:: -is_destructible(CPPVisibility min_vis) const { - // Do we have an explicit destructor? - CPPInstance *destructor = get_destructor(); - if (destructor != nullptr) { - if (destructor->_vis > min_vis) { - // Yes, but it's inaccessible. - return false; - } - - if (destructor->_storage_class & CPPInstance::SC_deleted) { - // Yes, but it's explicitly been deleted. - return false; - } - - return true; - } - - // Make sure all base classes are destructible. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr && !base->is_destructible(V_protected)) { - return false; - } - } - - assert(_scope != nullptr); - - // Make sure all members are destructible. - CPPScope::Variables::const_iterator vi; - for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) { - CPPInstance *instance = (*vi).second; - assert(instance != nullptr); - - if (instance->_storage_class & CPPInstance::SC_static) { - // Static members don't count. - continue; - } - - // If the data member is not destructible, no go. - assert(instance->_type != nullptr); - if (!instance->_type->is_destructible()) { - return false; - } - } - - return true; -} - -/** - * Returns true if variables of this type may be implicitly converted to - * the other type. - */ -bool CPPStructType:: -is_convertible_to(const CPPType *other) const { - if (CPPType::is_convertible_to(other)) { - return true; - } - - // Check all typecast operators to see whether we can cast to a type that is - // convertible to the other type. - CPPScope::Functions::const_iterator fi; - for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) { - CPPInstance *inst = (*ii); - - if (inst->_storage_class & (CPPInstance::SC_deleted | CPPInstance::SC_static | CPPInstance::SC_explicit)) { - // Exclude static/deleted/explicit methods. - continue; - } - - // Also, the instance needs to be publicly visible. - if (inst->_vis > V_public) { - continue; - } - - assert(inst->_type != nullptr); - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if (ftype->_return_type != nullptr && - (ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) { - // Yes, this is a typecast operator. Test using the return type. - if (ftype->_return_type->is_convertible_to(other)) { - return true; - } - } - } - } - - // Check whether any of the base classes are convertible. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr && (*di)._vis <= V_public && !base->is_convertible_to(other)) { - return true; - } - } - - return false; -} - -/** - * Ensures all functions are correctly marked with the "virtual" flag if they - * are truly virtual by virtue of inheritance, rather than simply being - * labeled virtual. - * - * This also sets the CPPInstance::SC_inherited_virtual flags on those virtual - * methods that override a virtual method defined in a parent class (as - * opposed to those that appear for this first time in this class). It is - * sometimes useful to know whether a given virtual method represents the - * first time that particular method appears. - * - * The return value is true if this class defines or inherits any virtual - * methods (and thus requires a virtual function pointer), or false otherwise. - */ -bool CPPStructType:: -check_virtual() const { - VFunctions funcs; - get_virtual_funcs(funcs); - return !funcs.empty(); -} - -/** - * Returns true if this class, or any of its base classes, has a virtual - * destructor. - */ -bool CPPStructType:: -has_virtual_destructor() const { - CPPInstance *destructor = get_destructor(); - if (destructor != nullptr) { - if (destructor->_storage_class & CPPInstance::SC_virtual) { - return true; - } - } - - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr && base->has_virtual_destructor()) { - return true; - } - } - - return false; -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPStructType:: -is_fully_specified() const { - if (_scope != nullptr && !_scope->is_fully_specified()) { - return false; - } - return CPPType::is_fully_specified(); -} - -/** - * Returns true if the type has not yet been fully specified, false if it has. - */ -bool CPPStructType:: -is_incomplete() const { - return _incomplete; -} - -/** - * Returns the constructor defined for the struct type, if any, or NULL if no - * constructor is found. - */ -CPPFunctionGroup *CPPStructType:: -get_constructor() const { - // Just look for the function with the same name as the class. - CPPScope::Functions::const_iterator fi; - fi = _scope->_functions.find(get_simple_name()); - if (fi != _scope->_functions.end()) { - return fi->second; - } else { - return nullptr; - } -} - -/** - * Returns the default constructor defined for the struct type, or NULL if - * there is no user-declared constructor that takes 0 arguments. - */ -CPPInstance *CPPStructType:: -get_default_constructor() const { - CPPFunctionGroup *fgroup = get_constructor(); - if (fgroup == nullptr) { - return nullptr; - } - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if (ftype->_parameters->_parameters.size() == 0 || - ftype->_parameters->_parameters.front()->_initializer != nullptr) { - // It takes 0 parameters (or all parameters have default values). - return inst; - } - } - - return nullptr; -} - -/** - * Returns the copy constructor defined for the struct type, or NULL if no - * user-declared copy constructor exists. - */ -CPPInstance *CPPStructType:: -get_copy_constructor() const { - CPPFunctionGroup *fgroup = get_constructor(); - if (fgroup == nullptr) { - return nullptr; - } - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if ((ftype->_flags & CPPFunctionType::F_copy_constructor) != 0) { - return inst; - } - } - - return nullptr; -} - -/** - * Returns the move constructor defined for the struct type, or NULL if no - * user-declared move constructor exists. - */ -CPPInstance *CPPStructType:: -get_move_constructor() const { - CPPFunctionGroup *fgroup = get_constructor(); - if (fgroup == nullptr) { - return nullptr; - } - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if ((ftype->_flags & CPPFunctionType::F_move_constructor) != 0) { - return inst; - } - } - - return nullptr; -} - -/** - * Returns the assignment operator defined for the struct type, if any, or - * NULL if no assignment operator is found. - */ -CPPFunctionGroup *CPPStructType:: -get_assignment_operator() const { - // Just look for the function with the name "operator =" - CPPScope::Functions::const_iterator fi; - fi = _scope->_functions.find("operator ="); - if (fi != _scope->_functions.end()) { - return fi->second; - } else { - return nullptr; - } -} - -/** - * Returns the copy assignment operator defined for the struct type, or NULL - * if no user-declared copy assignment operator exists. - */ -CPPInstance *CPPStructType:: -get_copy_assignment_operator() const { - CPPFunctionGroup *fgroup = get_assignment_operator(); - if (fgroup == nullptr) { - return nullptr; - } - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if ((ftype->_flags & CPPFunctionType::F_copy_assignment_operator) != 0) { - return inst; - } - } - - return nullptr; -} - -/** - * Returns the move assignment operator defined for the struct type, or NULL - * if no user-declared move assignment operator exists. - */ -CPPInstance *CPPStructType:: -get_move_assignment_operator() const { - CPPFunctionGroup *fgroup = get_assignment_operator(); - if (fgroup == nullptr) { - return nullptr; - } - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if ((ftype->_flags & CPPFunctionType::F_move_assignment_operator) != 0) { - return inst; - } - } - - return nullptr; -} - -/** - * Returns the destructor defined for the struct type, if any, or NULL if no - * user-declared destructor is found. - */ -CPPInstance *CPPStructType:: -get_destructor() const { - // Iterate through all the functions that begin with '~' until we find one - // that claims to be a destructor. In theory, there should only be one such - // function. - CPPScope::Functions::const_iterator fi; - fi = _scope->_functions.lower_bound("~"); - - while (fi != _scope->_functions.end() && - (*fi).first[0] == '~') { - CPPFunctionGroup *fgroup = (*fi).second; - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - assert(inst->_type != nullptr); - - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - - if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - return inst; - } - } - ++fi; - } - - return nullptr; -} - -/** - * - */ -CPPDeclaration *CPPStructType:: -instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - - // I *think* this assertion is no longer valid. Who knows. - // assert(!_incomplete); - - if (_scope == nullptr) { - if (error_sink != nullptr) { - error_sink->warning("Ignoring template parameters for class " + - get_local_name()); - } - return (CPPDeclaration *)this; - } - - CPPScope *scope = - _scope->instantiate(actual_params, current_scope, global_scope, error_sink); - - if (scope->get_struct_type()->get_scope() != scope) { - // Hmm, this type seems to be not completely defined. We must be in the - // middle of recursively instantiating the scope. Thus, we don't yet know - // what its associated struct type will be. - - // Postpone the evaluation of this type. - CPPIdentifier *ident = new CPPIdentifier(get_fully_scoped_name(), _file); - - return CPPType::new_type(new CPPTBDType(ident)); - } - - CPPType *result = scope->get_struct_type(); - result = CPPType::new_type(result); - if (result != (CPPType *)this) { - // This really means the method ought to be non-const. But I'm too lazy - // to propagate this change all the way back right now, so this hack is - // here. - ((CPPStructType *)this)->_instantiations.insert(result); - } - return result; -} - -/** - * - */ -CPPDeclaration *CPPStructType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - SubstDecl::const_iterator si = subst.find(this); - if (si != subst.end()) { - assert((*si).second != nullptr); - return (*si).second; - } - - if (_incomplete) { - // We haven't finished defining the class yet. - return this; - } - - if (_subst_decl_recursive_protect) { - // We're already executing this block; we'll have to return a proxy to the - // type which we'll define later. - CPPTypeProxy *proxy = new CPPTypeProxy; - _proxies.push_back(proxy); - assert(proxy != nullptr); - return proxy; - } - _subst_decl_recursive_protect = true; - - CPPStructType *rep = new CPPStructType(*this); - - if (_ident != nullptr) { - rep->_ident = - _ident->substitute_decl(subst, current_scope, global_scope); - } - - if (_scope != nullptr) { - rep->_scope = - _scope->substitute_decl(subst, current_scope, global_scope); - if (rep->_scope != _scope) { - rep->_scope->set_struct_type(rep); - - // If we just instantiated a template scope, write the template - // parameters into our identifier. - CPPScope *pscope = rep->_scope->get_parent_scope(); - - if (pscope != nullptr && - pscope->_name.has_templ()) { - - // If the struct name didn't have an explicit template reference - // before, now it does. - if (_ident != nullptr && !_ident->_names.empty() && !_ident->_names.back().has_templ()) { - if (rep->is_template()) { - rep->_template_scope = nullptr; - CPPNameComponent nc(get_simple_name()); - nc.set_templ(pscope->_name.get_templ()); - rep->_ident = new CPPIdentifier(nc, _file); - } - } - } - } - } - - bool unchanged = - (rep->_ident == _ident && rep->_scope == _scope); - - for (int i = 0; i < (int)_derivation.size(); ++i) { - rep->_derivation[i]._base = - _derivation[i]._base->substitute_decl(subst, current_scope, global_scope)->as_type(); - if (rep->_derivation[i]._base != _derivation[i]._base) { - unchanged = false; - } - } - - if (unchanged) { - delete rep; - rep = this; - } - - subst.insert(SubstDecl::value_type(this, rep)); - - _subst_decl_recursive_protect = false; - // Now fill in all the proxies we created for our recursive references. - Proxies::iterator pi; - for (pi = _proxies.begin(); pi != _proxies.end(); ++pi) { - (*pi)->_actual_type = rep; - } - - assert(rep != nullptr); - rep = CPPType::new_type(rep)->as_struct_type(); - assert(rep != nullptr); - if (rep != this) { - _instantiations.insert(rep); - } - return rep; -} - -/** - * - */ -void CPPStructType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (!complete && _ident != nullptr) { - // If we have a name, use it. - if (cppparser_output_class_keyword) { - out << _type << " "; - } - out << _ident->get_local_name(scope); - - if (is_template()) { - CPPTemplateScope *tscope = get_template_scope(); - tscope->_parameters.output(out, scope); - } - - } else { - if (is_template()) { - get_template_scope()->_parameters.write_formal(out, scope); - indent(out, indent_level); - } - out << _type; - - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - - if (_ident != nullptr) { - out << " " << _ident->get_local_name(scope); - } - - if (_final) { - out << " final"; - } - - // Show any derivation we may have - if (!_derivation.empty()) { - Derivation::const_iterator di = _derivation.begin(); - out << " : " << *di; - ++di; - while (di != _derivation.end()) { - out << ", " << *di; - ++di; - } - } - - out << " {\n"; - _scope->write(out, indent_level + 2, _scope); - indent(out, indent_level) << "}"; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPStructType:: -get_subtype() const { - return ST_struct; -} - -/** - * - */ -CPPStructType *CPPStructType:: -as_struct_type() { - return this; -} - - -/** - * Fills funcs up with a list of all the virtual function declarations (pure- - * virtual or otherwise) defined at or above this class. This is used to - * determine which functions in a given class are actually virtual, since a - * function is virtual whose parent class holds a virtual function by the same - * name, whether or not it is actually declared virtual in the derived class. - */ -void CPPStructType:: -get_virtual_funcs(VFunctions &funcs) const { - // First, get all the virtual funcs from our parents. - Derivation::const_iterator di; - for (di = _derivation.begin(); di != _derivation.end(); ++di) { - VFunctions vf; - CPPStructType *base = (*di)._base->as_struct_type(); - if (base != nullptr) { - base->get_virtual_funcs(vf); - funcs.splice(funcs.end(), vf); - } - } - - // Now look for matching functions in this class that we can now infer are - // virtual. - VFunctions::iterator vfi, vfnext; - vfi = funcs.begin(); - while (vfi != funcs.end()) { - vfnext = vfi; - ++vfnext; - - CPPInstance *inst = (*vfi); - assert(inst->_type != nullptr); - CPPFunctionType *base_ftype = inst->_type->as_function_type(); - assert(base_ftype != nullptr); - - if (inst->_storage_class & CPPInstance::SC_deleted) { - // Ignore deleted functions. - - } else if ((base_ftype->_flags & CPPFunctionType::F_destructor) != 0) { - // Match destructor-for-destructor; don't try to match destructors up by - // name. - CPPInstance *destructor = get_destructor(); - if (destructor != nullptr) { - // It's a match! This destructor is virtual. - funcs.erase(vfi); - destructor->_storage_class |= - (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual); - } - - } else { - // Non-destructors we can try to match up by name. - std::string fname = inst->get_local_name(); - CPPScope::Functions::const_iterator fi; - fi = _scope->_functions.find(fname); - - if (fi != _scope->_functions.end()) { - CPPFunctionGroup *fgroup = (*fi).second; - - // Look for a matching function amid this group. - bool match_found = false; - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end() && !match_found; - ++ii) { - CPPInstance *new_inst = (*ii); - assert(new_inst->_type != nullptr); - - CPPFunctionType *new_ftype = new_inst->_type->as_function_type(); - assert(new_ftype != nullptr); - - if (new_ftype->match_virtual_override(*base_ftype)) { - // It's a match! We now know it's virtual. Erase this function - // from the list, so we can add it back in below. - funcs.erase(vfi); - match_found = true; - - // In fact, it's not only definitely virtual, but it's *inherited* - // virtual, which means only that the interface is defined in some - // parent class. Sometimes this is useful to know. - new_inst->_storage_class |= - (CPPInstance::SC_virtual | CPPInstance::SC_inherited_virtual); - } - } - } - } - vfi = vfnext; - } - - // Finally, look for more virtual function definitions. - CPPScope::Functions::const_iterator fi; - for (fi = _scope->_functions.begin(); - fi != _scope->_functions.end(); - ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - if ((inst->_storage_class & CPPInstance::SC_virtual) != 0 && - (inst->_storage_class & CPPInstance::SC_deleted) == 0) { - // Here's a virtual function. - funcs.push_back(inst); - } - } - } -} - -/** - * Fills funcs up with a list of all the pure virtual function declarations - * defined at or above this class that have not been given definitions. - */ -void CPPStructType:: -get_pure_virtual_funcs(VFunctions &funcs) const { - // First, get all the virtual functions. - VFunctions vfuncs; - get_virtual_funcs(vfuncs); - - // Now traverse the list, getting out those functions that are pure virtual. - VFunctions::iterator vfi; - for (vfi = vfuncs.begin(); vfi != vfuncs.end(); ++vfi) { - CPPInstance *inst = (*vfi); - if ((inst->_storage_class & CPPInstance::SC_pure_virtual) != 0) { - funcs.push_back(inst); - } - } -} - -/** - * Called by CPPDeclaration to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPStructType:: -is_equal(const CPPDeclaration *other) const { - return CPPDeclaration::is_equal(other); - /* - const CPPStructType *ot = ((CPPDeclaration *)other)->as_struct_type(); - assert(ot != NULL); - - return this == ot || - (get_fully_scoped_name() == ot->get_fully_scoped_name()); - */ -} - -/** - * Called by CPPDeclaration to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPStructType:: -is_less(const CPPDeclaration *other) const { - return CPPDeclaration::is_less(other); - /* - const CPPStructType *ot = ((CPPDeclaration *)other)->as_struct_type(); - assert(ot != NULL); - - if (this == ot) { - return false; - } - - return - (get_fully_scoped_name() < ot->get_fully_scoped_name()); - */ -} diff --git a/dtool/src/cppparser/cppStructType.h b/dtool/src/cppparser/cppStructType.h deleted file mode 100644 index c3eb8f1bae..0000000000 --- a/dtool/src/cppparser/cppStructType.h +++ /dev/null @@ -1,132 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppStructType.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPSTRUCTTYPE_H -#define CPPSTRUCTTYPE_H - -#include "dtoolbase.h" - -#include "cppIdentifier.h" -#include "cppExtensionType.h" -#include "cppFunctionGroup.h" -#include "cppVisibility.h" - -#include -#include - -class CPPScope; -class CPPTypeProxy; - -/** - * - */ -class CPPStructType : public CPPExtensionType { -public: - CPPStructType(Type type, CPPIdentifier *ident, - CPPScope *current_scope, - CPPScope *scope, - const CPPFile &file, - CPPAttributeList attr = CPPAttributeList()); - CPPStructType(const CPPStructType ©); - void operator = (const CPPStructType ©); - - void append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual); - - CPPScope *get_scope() const; - - bool is_abstract() const; - bool is_base_of(const CPPStructType *other) const; - bool is_empty() const; - bool is_polymorphic() const; - bool check_virtual() const; - bool has_virtual_destructor() const; - virtual bool is_fully_specified() const; - virtual bool is_incomplete() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *arg_type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - virtual bool is_destructible() const; - bool is_default_constructible(CPPVisibility min_vis) const; - bool is_copy_constructible(CPPVisibility min_vis) const; - bool is_move_constructible(CPPVisibility min_vis = V_public) const; - bool is_copy_assignable(CPPVisibility min_vis) const; - bool is_move_assignable(CPPVisibility min_vis = V_public) const; - bool is_destructible(CPPVisibility min_vis) const; - virtual bool is_convertible_to(const CPPType *other) const; - - inline bool is_final() const { return _final; } - - CPPFunctionGroup *get_constructor() const; - CPPInstance *get_default_constructor() const; - CPPInstance *get_copy_constructor() const; - CPPInstance *get_move_constructor() const; - CPPFunctionGroup *get_assignment_operator() const; - CPPInstance *get_copy_assignment_operator() const; - CPPInstance *get_move_assignment_operator() const; - CPPInstance *get_destructor() const; - - virtual CPPDeclaration * - instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPStructType *as_struct_type(); - - CPPScope *_scope; - bool _incomplete; - bool _final; - - class Base { - public: - void output(std::ostream &out) const; - - CPPType *_base; - CPPVisibility _vis; - bool _is_virtual; - }; - - typedef std::vector Derivation; - Derivation _derivation; - - typedef std::list VFunctions; - void get_virtual_funcs(VFunctions &funcs) const; - void get_pure_virtual_funcs(VFunctions &funcs) const; - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; - - bool _subst_decl_recursive_protect; - typedef std::vector Proxies; - Proxies _proxies; -}; - -inline std::ostream &operator << (std::ostream &out, const CPPStructType::Base &base) { - base.output(out); - return out; -} - - -#endif diff --git a/dtool/src/cppparser/cppTBDType.cxx b/dtool/src/cppparser/cppTBDType.cxx deleted file mode 100644 index 5c583453ca..0000000000 --- a/dtool/src/cppparser/cppTBDType.cxx +++ /dev/null @@ -1,175 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTBDType.cxx - * @author drose - * @date 1999-11-05 - */ - -#include "cppTBDType.h" -#include "cppIdentifier.h" - -#include "cppSimpleType.h" - -/** - * - */ -CPPTBDType:: -CPPTBDType(CPPIdentifier *ident) : - CPPType(CPPFile()), - _ident(ident) -{ - _subst_decl_recursive_protect = false; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPTBDType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *type = _ident->find_type(current_scope, global_scope); - if (type != nullptr) { - return type; - } - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPTBDType:: -is_tbd() const { - return true; -} - -/** - * Returns a fundametal one-word name for the type. This name will not - * include any scoping operators or template parameters, so it may not be a - * compilable reference to the type. - */ -std::string CPPTBDType:: -get_simple_name() const { - return _ident->get_simple_name(); -} - -/** - * Returns the compilable, correct name for this type within the indicated - * scope. If the scope is NULL, within the scope the type is declared in. - */ -std::string CPPTBDType:: -get_local_name(CPPScope *scope) const { - return _ident->get_local_name(scope); -} - -/** - * Returns the compilable, correct name for the type, with completely explicit - * scoping. - */ -std::string CPPTBDType:: -get_fully_scoped_name() const { - return _ident->get_fully_scoped_name(); -} - -/** - * - */ -CPPDeclaration *CPPTBDType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPDeclaration *top = - CPPDeclaration::substitute_decl(subst, current_scope, global_scope); - if (top != this) { - return top; - } - - // Protect against recursive entry into this function block. I know it's - // ugly--have you got any better suggestions? - if (_subst_decl_recursive_protect) { - // We're already executing this block. - return this; - } - _subst_decl_recursive_protect = true; - - CPPTBDType *rep = new CPPTBDType(*this); - rep->_ident = _ident->substitute_decl(subst, current_scope, global_scope); - - if (rep->_ident == _ident) { - delete rep; - rep = this; - } - - rep = CPPType::new_type(rep)->as_tbd_type(); - assert(rep != nullptr); - - CPPType *result = rep; - - // Can we now define it as a real type? - CPPType *type = rep->_ident->find_type(current_scope, global_scope, subst); - if (type != nullptr) { - result = type; - } - - subst.insert(SubstDecl::value_type(this, result)); - - _subst_decl_recursive_protect = false; - return result; -} - -/** - * - */ -void CPPTBDType:: -output(std::ostream &out, int, CPPScope *, bool) const { - out /* << "typename " */ << *_ident; -} - -/** - * - */ -CPPDeclaration::SubType CPPTBDType:: -get_subtype() const { - return ST_tbd; -} - -/** - * - */ -CPPTBDType *CPPTBDType:: -as_tbd_type() { - return this; -} - - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPTBDType:: -is_equal(const CPPDeclaration *other) const { - const CPPTBDType *ot = ((CPPDeclaration *)other)->as_tbd_type(); - assert(ot != nullptr); - - return (*_ident) == (*ot->_ident); -} - - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPTBDType:: -is_less(const CPPDeclaration *other) const { - const CPPTBDType *ot = ((CPPDeclaration *)other)->as_tbd_type(); - assert(ot != nullptr); - - return (*_ident) < (*ot->_ident); -} diff --git a/dtool/src/cppparser/cppTBDType.h b/dtool/src/cppparser/cppTBDType.h deleted file mode 100644 index beec68adeb..0000000000 --- a/dtool/src/cppparser/cppTBDType.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTBDType.h - * @author drose - * @date 1999-11-05 - */ - -#ifndef CPPTBDTYPE_H -#define CPPTBDTYPE_H - -#include "dtoolbase.h" - -#include "cppType.h" - -class CPPIdentifier; - -/** - * This represents a type whose exact meaning is still to-be-determined. It - * happens when a typename is referenced in a template class (especially using - * the 'typename' keyword) but the actual type cannot be known until the class - * is instantiated. - */ -class CPPTBDType : public CPPType { -public: - CPPTBDType(CPPIdentifier *ident); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPTBDType *as_tbd_type(); - - CPPIdentifier *_ident; - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; - -private: - bool _subst_decl_recursive_protect; -}; - -#endif diff --git a/dtool/src/cppparser/cppTemplateParameterList.cxx b/dtool/src/cppparser/cppTemplateParameterList.cxx deleted file mode 100644 index fd12967711..0000000000 --- a/dtool/src/cppparser/cppTemplateParameterList.cxx +++ /dev/null @@ -1,234 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTemplateParameterList.cxx - * @author drose - * @date 1999-10-28 - */ - -#include "cppTemplateParameterList.h" -#include "cppClassTemplateParameter.h" -#include "cppInstance.h" -#include "cppExpression.h" - -/** - * - */ -CPPTemplateParameterList:: -CPPTemplateParameterList() { -} - -/** - * - */ -std::string CPPTemplateParameterList:: -get_string() const { - std::ostringstream strname; - strname << "< " << *this << " >"; - return strname.str(); -} - -/** - * Matches up the actual parameters one-to-one with the formal parameters they - * are replacing, so the template may be instantiated by swapping out each - * occurrence of a template standin type with its appropriate replacement. - */ -void CPPTemplateParameterList:: -build_subst_decl(const CPPTemplateParameterList &formal_params, - CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) const { - - Parameters::const_iterator pfi, pai; - for (pfi = formal_params._parameters.begin(), pai = _parameters.begin(); - pfi != formal_params._parameters.end() && pai != _parameters.end(); - ++pfi, ++pai) { - CPPDeclaration *formal = *pfi; - CPPDeclaration *actual = *pai; - - if (actual->as_type()) { - actual = actual->as_type()->resolve_type(current_scope, global_scope); - } - - if (!(formal == actual)) { - subst.insert(CPPDeclaration::SubstDecl::value_type(formal, actual)); - } - } - - // Fill in the default template parameters. - while (pfi != formal_params._parameters.end()) { - CPPDeclaration *decl = (*pfi); - if (decl->as_instance()) { - // A value template parameter. Its default is an expression. - CPPInstance *inst = decl->as_instance(); - if (inst->_initializer != nullptr) { - CPPDeclaration *decl = - inst->_initializer->substitute_decl(subst, current_scope, - global_scope); - if (!(*decl == *inst)) { - subst.insert(CPPDeclaration::SubstDecl::value_type - (inst, decl)); - } - } - } else if (decl->as_class_template_parameter()) { - // A class template parameter. - CPPClassTemplateParameter *cparam = decl->as_class_template_parameter(); - if (cparam->_default_type != nullptr) { - CPPDeclaration *decl = - cparam->_default_type->substitute_decl(subst, current_scope, - global_scope); - if (!(*cparam == *decl)) { - subst.insert(CPPDeclaration::SubstDecl::value_type - (cparam, decl)); - } - } - } - ++pfi; - } -} - -/** - * This function returns true if all the parameters in the list are real - * expressions or classes, and not types yet to-be-determined or template - * parameter types. That is, this returns true for a normal template - * instantiation, and false for a template instantiation based on template - * parameters that have not yet been specified. - */ -bool CPPTemplateParameterList:: -is_fully_specified() const { - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (!_parameters[i]->is_fully_specified()) { - return false; - } - } - return true; -} - -/** - * Returns true if any type within the parameter list is a CPPTBDType and thus - * isn't fully determined right now. - */ -bool CPPTemplateParameterList:: -is_tbd() const { - for (int i = 0; i < (int)_parameters.size(); ++i) { - CPPType *type = _parameters[i]->as_type(); - if (type != nullptr && - (type->is_tbd() || type->as_class_template_parameter() != nullptr)) { - return true; - } - CPPExpression *expr = _parameters[i]->as_expression(); - if (expr != nullptr && expr->is_tbd()) { - return true; - } - } - return false; -} - -/** - * - */ -bool CPPTemplateParameterList:: -operator == (const CPPTemplateParameterList &other) const { - if (_parameters.size() != other._parameters.size()) { - return false; - } - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (*_parameters[i] != *other._parameters[i]) { - return false; - } - } - return true; -} - -/** - * - */ -bool CPPTemplateParameterList:: -operator != (const CPPTemplateParameterList &other) const { - return !(*this == other); -} - -/** - * - */ -bool CPPTemplateParameterList:: -operator < (const CPPTemplateParameterList &other) const { - if (_parameters.size() != other._parameters.size()) { - return _parameters.size() < other._parameters.size(); - } - for (int i = 0; i < (int)_parameters.size(); ++i) { - if (*_parameters[i] != *other._parameters[i]) { - return *_parameters[i] < *other._parameters[i]; - } - } - return false; -} - -/** - * - */ -CPPTemplateParameterList *CPPTemplateParameterList:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPTemplateParameterList *rep = new CPPTemplateParameterList(*this); - - bool anything_changed = false; - for (int i = 0; i < (int)rep->_parameters.size(); ++i) { - rep->_parameters[i] = - _parameters[i]->substitute_decl(subst, current_scope, global_scope); - if (rep->_parameters[i] != _parameters[i]) { - anything_changed = true; - } - } - - if (!anything_changed) { - delete rep; - rep = this; - } - - return rep; -} - -/** - * - */ -void CPPTemplateParameterList:: -output(std::ostream &out, CPPScope *scope) const { - if (!_parameters.empty()) { - Parameters::const_iterator pi = _parameters.begin(); - (*pi)->output(out, 0, scope, false); - - ++pi; - while (pi != _parameters.end()) { - out << ", "; - (*pi)->output(out, 0, scope, false); - ++pi; - } - } -} - -/** - * Writes the list as a set of formal parameters for a template scope. - * Includes the keyword "template" and the angle brackets, as well as the - * trailing newline. - */ -void CPPTemplateParameterList:: -write_formal(std::ostream &out, CPPScope *scope) const { - out << "template<"; - if (!_parameters.empty()) { - Parameters::const_iterator pi = _parameters.begin(); - (*pi)->output(out, 0, scope, true); - - ++pi; - while (pi != _parameters.end()) { - out << ", "; - (*pi)->output(out, 0, scope, true); - ++pi; - } - } - out << ">\n"; -} diff --git a/dtool/src/cppparser/cppTemplateParameterList.h b/dtool/src/cppparser/cppTemplateParameterList.h deleted file mode 100644 index d47f8fdd9e..0000000000 --- a/dtool/src/cppparser/cppTemplateParameterList.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTemplateParameterList.h - * @author drose - * @date 1999-10-28 - */ - -#ifndef CPPTEMPLATEPARAMETERLIST_H -#define CPPTEMPLATEPARAMETERLIST_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -#include -#include - -class CPPScope; - -/** - * This class serves to store the parameter list for a template function or - * class, both for the formal parameter list (given when the template is - * defined) and for the actual parameter list (given when the template is - * instantiated). - */ -class CPPTemplateParameterList { -public: - CPPTemplateParameterList(); - - std::string get_string() const; - void build_subst_decl(const CPPTemplateParameterList &formal_params, - CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) const; - - bool is_fully_specified() const; - bool is_tbd() const; - - bool operator == (const CPPTemplateParameterList &other) const; - bool operator != (const CPPTemplateParameterList &other) const; - bool operator < (const CPPTemplateParameterList &other) const; - - CPPTemplateParameterList *substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - void output(std::ostream &out, CPPScope *scope) const; - void write_formal(std::ostream &out, CPPScope *scope) const; - - typedef std::vector Parameters; - Parameters _parameters; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPTemplateParameterList &plist) { - plist.output(out, nullptr); - return out; -} - - -// This is an STL function object used to uniquely order -// CPPTemplateParameterList pointers. -class CPPTPLCompare { -public: - bool operator () (const CPPTemplateParameterList *a, - const CPPTemplateParameterList *b) const { - return (*a) < (*b); - } -}; - -#endif diff --git a/dtool/src/cppparser/cppTemplateScope.cxx b/dtool/src/cppparser/cppTemplateScope.cxx deleted file mode 100644 index a71c176005..0000000000 --- a/dtool/src/cppparser/cppTemplateScope.cxx +++ /dev/null @@ -1,172 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTemplateScope.cxx - * @author drose - * @date 1999-10-28 - */ - -#include "cppTemplateScope.h" -#include "cppExtensionType.h" -#include "cppClassTemplateParameter.h" -#include "cppIdentifier.h" -#include "cppTypedefType.h" - -using std::string; - -/** - * - */ -CPPTemplateScope:: -CPPTemplateScope(CPPScope *parent_scope) : - CPPScope(parent_scope, CPPNameComponent("template"), V_public) -{ -} - - -/** - * - */ -void CPPTemplateScope:: -add_declaration(CPPDeclaration *decl, CPPScope *global_scope, - CPPPreprocessor *preprocessor, - const cppyyltype &pos) { - decl->_template_scope = this; - assert(_parent_scope != nullptr); - _parent_scope->add_declaration(decl, global_scope, preprocessor, pos); -} - -/** - * - */ -void CPPTemplateScope:: -add_enum_value(CPPInstance *inst) { - inst->_template_scope = this; - assert(_parent_scope != nullptr); - _parent_scope->add_enum_value(inst); -} - -/** - * - */ -void CPPTemplateScope:: -define_typedef_type(CPPTypedefType *type, CPPPreprocessor *error_sink) { - type->_template_scope = this; - assert(_parent_scope != nullptr); - _parent_scope->define_typedef_type(type, error_sink); -} - -/** - * - */ -void CPPTemplateScope:: -define_extension_type(CPPExtensionType *type, CPPPreprocessor *error_sink) { - type->_template_scope = this; - assert(_parent_scope != nullptr); - _parent_scope->define_extension_type(type, error_sink); -} - -/** - * - */ -void CPPTemplateScope:: -define_namespace(CPPNamespace *scope) { - assert(_parent_scope != nullptr); - _parent_scope->define_namespace(scope); -} - -/** - * - */ -void CPPTemplateScope:: -add_using(CPPUsing *using_decl, CPPScope *global_scope, - CPPPreprocessor *error_sink) { - assert(_parent_scope != nullptr); - _parent_scope->add_using(using_decl, global_scope, error_sink); -} - -/** - * - */ -void CPPTemplateScope:: -add_template_parameter(CPPDeclaration *param) { - _parameters._parameters.push_back(param); - CPPClassTemplateParameter *cl = param->as_class_template_parameter(); - if (cl != nullptr) { - // Create an implicit typedef for this class parameter. - if (cl->_ident != nullptr) { - string name = cl->_ident->get_local_name(); - _types[name] = cl; - } - } - - CPPInstance *inst = param->as_instance(); - if (inst != nullptr) { - // Register the variable for this value parameter. - string name = inst->get_local_name(); - if (!name.empty()) { - _variables[name] = inst; - } - } -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPTemplateScope:: -is_fully_specified() const { - return false; -} - -/** - * - */ -string CPPTemplateScope:: -get_simple_name() const { - assert(_parent_scope != nullptr); - return _parent_scope->get_simple_name(); -} - -/** - * - */ -string CPPTemplateScope:: -get_local_name(CPPScope *scope) const { - assert(_parent_scope != nullptr); - return _parent_scope->get_local_name(scope); -} - -/** - * - */ -string CPPTemplateScope:: -get_fully_scoped_name() const { - assert(_parent_scope != nullptr); - return _parent_scope->get_fully_scoped_name(); -} - -/** - * - */ -void CPPTemplateScope:: -output(std::ostream &out, CPPScope *scope) const { - CPPScope::output(out, scope); - out << "< "; - _parameters.output(out, scope); - out << " >"; -} - -/** - * - */ -CPPTemplateScope *CPPTemplateScope:: -as_template_scope() { - return this; -} diff --git a/dtool/src/cppparser/cppTemplateScope.h b/dtool/src/cppparser/cppTemplateScope.h deleted file mode 100644 index 8a30b686a5..0000000000 --- a/dtool/src/cppparser/cppTemplateScope.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTemplateScope.h - * @author drose - * @date 1999-10-28 - */ - -#ifndef CPPTEMPLATESCOPE_H -#define CPPTEMPLATESCOPE_H - -#include "dtoolbase.h" - -#include "cppScope.h" -#include "cppTemplateParameterList.h" - -/** - * This is an implicit scope that is created following the appearance of a - * "template" or some such line in a C++ file. It simply - * defines the template parameters. - */ -class CPPTemplateScope : public CPPScope { -public: - CPPTemplateScope(CPPScope *parent_scope); - - void add_template_parameter(CPPDeclaration *param); - - virtual void add_declaration(CPPDeclaration *decl, CPPScope *global_scope, - CPPPreprocessor *preprocessor, - const cppyyltype &pos); - virtual void add_enum_value(CPPInstance *inst); - virtual void define_typedef_type(CPPTypedefType *type, - CPPPreprocessor *error_sink = nullptr); - virtual void define_extension_type(CPPExtensionType *type, - CPPPreprocessor *error_sink = nullptr); - virtual void define_namespace(CPPNamespace *scope); - virtual void add_using(CPPUsing *using_decl, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr); - - virtual bool is_fully_specified() const; - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual void output(std::ostream &out, CPPScope *scope) const; - - virtual CPPTemplateScope *as_template_scope(); - - CPPTemplateParameterList _parameters; -}; - -#endif diff --git a/dtool/src/cppparser/cppToken.cxx b/dtool/src/cppparser/cppToken.cxx deleted file mode 100644 index daa624f17f..0000000000 --- a/dtool/src/cppparser/cppToken.cxx +++ /dev/null @@ -1,1327 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppToken.cxx - * @author drose - * @date 1999-10-22 - */ - -#include "cppToken.h" -#include "cppExpression.h" -#include "cppIdentifier.h" -#include "cppBison.h" -#include "pdtoa.h" - -#include - -/** - * - */ -CPPToken:: -CPPToken(int token, int line_number, int col_number, - const CPPFile &file, const std::string &str, - const YYSTYPE &lval) : - _token(token), _lval(lval) -{ - _lval.str = str; - _lloc.first_line = line_number; - _lloc.first_column = col_number; - _lloc.last_line = line_number; - _lloc.last_column = col_number; - _lloc.file = file; -} - -/** - * - */ -CPPToken:: -CPPToken(int token, const YYLTYPE &loc, const std::string &str, const YYSTYPE &val) : - _token(token), _lval(val), _lloc(loc) -{ - _lval.str = str; -} - -/** - * A named constructor for the token returned when the end of file has been - * reached. - */ -CPPToken CPPToken:: -eof() { - return CPPToken(0); -} - -/** - * Returns true if this is the EOF token. - */ -bool CPPToken:: -is_eof() const { - return _token == 0; -} - -/** - * - */ -void CPPToken:: -output(std::ostream &out) const { - switch (_token) { - case REAL: - out << "REAL " << _lval.u.real; - break; - - case INTEGER: - out << "INTEGER " << _lval.u.integer; - break; - - case CHAR_TOK: - out << "CHAR_TOK " << _lval.u.integer << " = " << _lval.str; - break; - - case SIMPLE_STRING: - out << "SIMPLE_STRING " << _lval.str; - break; - - case STRING_LITERAL: - out << "STRING_LITERAL " << *_lval.u.expr; - break; - - case SIMPLE_IDENTIFIER: - out << "SIMPLE_IDENTIFIER " << _lval.str; - break; - - case IDENTIFIER: - out << "IDENTIFIER " << *_lval.u.identifier; - break; - - case TYPENAME_IDENTIFIER: - out << "TYPENAME_IDENTIFIER " << *_lval.u.identifier; - break; - - case SCOPING: - out << "SCOPING " << *_lval.u.identifier << "::"; - break; - - case TYPEDEFNAME: - out << "TYPEDEFNAME " << _lval.str; - break; - - case ELLIPSIS: - out << "ELLIPSIS"; - break; - - case OROR: - out << "OROR"; - break; - - case ANDAND: - out << "ANDAND"; - break; - - case EQCOMPARE: - out << "EQCOMPARE"; - break; - - case NECOMPARE: - out << "NECOMPARE"; - break; - - case LECOMPARE: - out << "LECOMPARE"; - break; - - case GECOMPARE: - out << "GECOMPARE"; - break; - - case LSHIFT: - out << "LSHIFT"; - break; - - case RSHIFT: - out << "RSHIFT"; - break; - - case POINTSAT_STAR: - out << "POINTSAT_STAR"; - break; - - case DOT_STAR: - out << "DOT_STAR"; - break; - - case UNARY_NOT: - out << "UNARY_NOT"; - break; - - case UNARY_MINUS: - out << "UNARY_MINUS"; - break; - - case UNARY_PLUS: - out << "UNARY_PLUS"; - break; - - case UNARY_NEGATE: - out << "UNARY_NEGATE"; - break; - - case UNARY_STAR: - out << "UNARY_STAR"; - break; - - case UNARY_REF: - out << "UNARY_REF"; - break; - - case POINTSAT: - out << "POINTSAT"; - break; - - case SCOPE: - out << "SCOPE"; - break; - - case PLUSPLUS: - out << "PLUSPLUS"; - break; - - case MINUSMINUS: - out << "MINUSMINUS"; - break; - - case TIMESEQUAL: - out << "TIMESEQUAL"; - break; - - case DIVIDEEQUAL: - out << "DIVIDEEQUAL"; - break; - - case MODEQUAL: - out << "MODEQUAL"; - break; - - case PLUSEQUAL: - out << "PLUSEQUAL"; - break; - - case MINUSEQUAL: - out << "MINUSEQUAL"; - break; - - case OREQUAL: - out << "OREQUAL"; - break; - - case ANDEQUAL: - out << "ANDEQUAL"; - break; - - case XOREQUAL: - out << "XOREQUAL"; - break; - - case LSHIFTEQUAL: - out << "LSHIFTEQUAL"; - break; - - case RSHIFTEQUAL: - out << "RSHIFTEQUAL"; - break; - - case ATTR_LEFT: - out << "ATTR_LEFT"; - break; - - case ATTR_RIGHT: - out << "ATTR_RIGHT"; - break; - - case KW_ALIGNAS: - out << "KW_ALIGNAS"; - break; - - case KW_ALIGNOF: - out << "KW_ALIGNOF"; - break; - - case KW_AUTO: - out << "KW_AUTO"; - break; - - case KW_BEGIN_PUBLISH: - out << "KW_BEGIN_PUBLISH"; - break; - - case KW_BLOCKING: - out << "KW_BLOCKING"; - break; - - case KW_BOOL: - out << "KW_BOOL"; - break; - - case KW_BUILTIN_VA_LIST: - out << "KW_BUILTIN_VA_LIST"; - break; - - case KW_CATCH: - out << "KW_CATCH"; - break; - - case KW_CHAR: - out << "KW_CHAR"; - break; - - case KW_CHAR8_T: - out << "KW_CHAR8_T"; - break; - - case KW_CHAR16_T: - out << "KW_CHAR16_T"; - break; - - case KW_CHAR32_T: - out << "KW_CHAR32_T"; - break; - - case KW_CLASS: - out << "KW_CLASS"; - break; - - case KW_CONST: - out << "KW_CONST"; - break; - - case KW_CONSTEVAL: - out << "KW_CONSTEVAL"; - break; - - case KW_CONSTEXPR: - out << "KW_CONSTEXPR"; - break; - - case KW_CONSTINIT: - out << "KW_CONSTINIT"; - break; - - case KW_DECLTYPE: - out << "KW_DECLTYPE"; - break; - - case KW_DEFAULT: - out << "KW_DECLTYPE"; - break; - - case KW_DELETE: - out << "KW_DELETE"; - break; - - case KW_DOUBLE: - out << "KW_DOUBLE"; - break; - - case KW_DYNAMIC_CAST: - out << "KW_DYNAMIC_CAST"; - break; - - case KW_ELSE: - out << "KW_ELSE"; - break; - - case KW_ENUM: - out << "KW_ENUM"; - break; - - case KW_EXPLICIT: - out << "KW_EXPLICIT"; - break; - - case KW_EXPLICIT_LPAREN: - out << "KW_EXPLICIT_LPAREN"; - break; - - case KW_EXTENSION: - out << "KW_EXTENSION"; - break; - - case KW_EXTERN: - out << "KW_EXTERN"; - break; - - case KW_FALSE: - out << "KW_FALSE"; - break; - - case KW_FINAL: - out << "KW_FINAL"; - break; - - case KW_FLOAT: - out << "KW_FLOAT"; - break; - - case KW_FRIEND: - out << "KW_FRIEND"; - break; - - case KW_FOR: - out << "KW_FOR"; - break; - - case KW_GOTO: - out << "KW_GOTO"; - break; - - case KW_HAS_VIRTUAL_DESTRUCTOR: - out << "KW_HAS_VIRTUAL_DESTRUCTOR"; - break; - - case KW_IF: - out << "KW_IF"; - break; - - case KW_INLINE: - out << "KW_INLINE"; - break; - - case KW_INT: - out << "KW_INT"; - break; - - case KW_IS_ABSTRACT: - out << "KW_IS_ABSTRACT"; - break; - - case KW_IS_BASE_OF: - out << "KW_IS_BASE_OF"; - break; - - case KW_IS_CLASS: - out << "KW_IS_CLASS"; - break; - - case KW_IS_CONSTRUCTIBLE: - out << "KW_IS_CONSTRUCTIBLE"; - break; - - case KW_IS_CONVERTIBLE_TO: - out << "KW_IS_CONVERTIBLE_TO"; - break; - - case KW_IS_DESTRUCTIBLE: - out << "KW_IS_DESTRUCTIBLE"; - break; - - case KW_IS_EMPTY: - out << "KW_IS_EMPTY"; - break; - - case KW_IS_ENUM: - out << "KW_IS_ENUM"; - break; - - case KW_IS_FINAL: - out << "KW_IS_FINAL"; - break; - - case KW_IS_FUNDAMENTAL: - out << "KW_IS_FUNDAMENTAL"; - break; - - case KW_IS_POD: - out << "KW_IS_POD"; - break; - - case KW_IS_POLYMORPHIC: - out << "KW_IS_POLYMORPHIC"; - break; - - case KW_IS_STANDARD_LAYOUT: - out << "KW_IS_STANDARD_LAYOUT"; - break; - - case KW_IS_TRIVIAL: - out << "KW_IS_TRIVIAL"; - break; - - case KW_IS_TRIVIALLY_COPYABLE: - out << "KW_IS_TRIVIALLY_COPYABLE"; - break; - - case KW_IS_UNION: - out << "KW_IS_UNION"; - break; - - case KW_LONG: - out << "KW_LONG"; - break; - - case KW_MAKE_MAP_KEYS_SEQ: - out << "KW_MAKE_MAP_KEYS_SEQ"; - break; - - case KW_MAKE_MAP_PROPERTY: - out << "KW_MAKE_MAP_PROPERTY"; - break; - - case KW_MAKE_PROPERTY: - out << "KW_MAKE_PROPERTY"; - break; - - case KW_MAKE_PROPERTY2: - out << "KW_MAKE_PROPERTY2"; - break; - - case KW_MAKE_SEQ: - out << "KW_MAKE_SEQ"; - break; - - case KW_MAKE_SEQ_PROPERTY: - out << "KW_MAKE_SEQ_PROPERTY"; - break; - - case KW_MUTABLE: - out << "KW_MUTABLE"; - break; - - case KW_NAMESPACE: - out << "KW_NAMESPACE"; - break; - - case KW_NEW: - out << "KW_NEW"; - break; - - case KW_NOEXCEPT: - out << "KW_NOEXCEPT"; - break; - - case KW_NOEXCEPT_LPAREN: - out << "KW_NOEXCEPT_LPAREN"; - break; - - case KW_NULLPTR: - out << "KW_NULLPTR"; - break; - - case KW_OPERATOR: - if (_lval.u.identifier != nullptr) { - out << *_lval.u.identifier << "::"; - } - out << "KW_OPERATOR"; - break; - - case KW_OVERRIDE: - out << "KW_OVERRIDE"; - break; - - case KW_PRIVATE: - out << "KW_PRIVATE"; - break; - - case KW_PROTECTED: - out << "KW_PROTECTED"; - break; - - case KW_PUBLIC: - out << "KW_PUBLIC"; - break; - - case KW_PUBLISHED: - out << "KW_PUBLISHED"; - break; - - case KW_REGISTER: - out << "KW_REGISTER"; - break; - - case KW_REINTERPRET_CAST: - out << "KW_REINTERPRET_CAST"; - break; - - case KW_RESTRICT: - out << "KW_RESTRICT"; - break; - - case KW_RETURN: - out << "KW_RETURN"; - break; - - case KW_SHORT: - out << "KW_SHORT"; - break; - - case KW_SIGNED: - out << "KW_SIGNED"; - break; - - case KW_SIZEOF: - out << "KW_SIZEOF"; - break; - - case KW_STATIC: - out << "KW_STATIC"; - break; - - case KW_STATIC_ASSERT: - out << "KW_STATIC_ASSERT"; - break; - - case KW_STATIC_CAST: - out << "KW_STATIC_CAST"; - break; - - case KW_STRUCT: - out << "KW_STRUCT"; - break; - - case KW_TEMPLATE: - out << "KW_TEMPLATE"; - break; - - case KW_THREAD_LOCAL: - out << "KW_THREAD_LOCAL"; - break; - - case KW_THROW: - out << "KW_THROW"; - break; - - case KW_TRUE: - out << "KW_TRUE"; - break; - - case KW_TRY: - out << "KW_TRY"; - break; - - case KW_TYPEDEF: - out << "KW_TYPEDEF"; - break; - - case KW_TYPEID: - out << "KW_TYPEID"; - break; - - case KW_TYPENAME: - out << "KW_TYPENAME"; - break; - - case KW_UNDERLYING_TYPE: - out << "KW_UNDERLYING_TYPE"; - break; - - case KW_USING: - out << "KW_USING"; - break; - - case KW_UNION: - out << "KW_UNION"; - break; - - case KW_UNSIGNED: - out << "KW_UNSIGNED"; - break; - - case KW_VIRTUAL: - out << "KW_VIRTUAL"; - break; - - case KW_VOID: - out << "KW_VOID"; - break; - - case KW_VOLATILE: - out << "KW_VOLATILE"; - break; - - case KW_WCHAR_T: - out << "KW_WCHAR_T"; - break; - - case KW_WHILE: - out << "KW_WHILE"; - break; - - case START_CPP: - out << "START_CPP"; - break; - - case START_CONST_EXPR: - out << "START_CONST_EXPR"; - break; - - case START_TYPE: - out << "START_TYPE"; - break; - - default: - if (_token < 128 && isprint(_token)) { - out << "'" << (char)_token << "'"; - } else { - out << "token " << _token << "\n"; - } - } -} - -/** - * - */ -void CPPToken:: -output_code(std::ostream &out) const { - switch (_token) { - case REAL: - { - char buffer[128]; - pdtoa(_lval.u.real, buffer); - out << buffer; - } - break; - - case INTEGER: - out << _lval.u.integer; - break; - - case CHAR_TOK: - case SIMPLE_STRING: - out << (_token == CHAR_TOK ? '\'' : '"'); - for (char c : _lval.str) { - switch (c) { - case '\n': - out << "\\n"; - break; - - case '\t': - out << "\\t"; - break; - - case '\r': - out << "\\r"; - break; - - case '\a': - out << "\\a"; - break; - - case '\b': - out << "\\b"; - break; - - case '\v': - out << "\\v"; - break; - - case '\f': - out << "\\f"; - break; - - case '\'': - out << (_token == CHAR_TOK ? "\\\'" : "'"); - break; - - case '"': - out << (_token == CHAR_TOK ? "\"" : "\\\""); - break; - - case '\\': - out << "\\\\"; - break; - - default: - if (isprint(c)) { - out << c; - } else { - out << '\\' << std::oct << std::setw(3) << std::setfill('0') << (int)(c) - << std::dec << std::setw(0); - } - break; - } - } - out << (_token == CHAR_TOK ? '\'' : '"'); - break; - - case STRING_LITERAL: - out << *_lval.u.expr; - break; - - case SIMPLE_IDENTIFIER: - out << _lval.str; - break; - - case IDENTIFIER: - out << *_lval.u.identifier; - break; - - case TYPENAME_IDENTIFIER: - out << *_lval.u.identifier; - break; - - case SCOPING: - out << *_lval.u.identifier << "::"; - break; - - case TYPEDEFNAME: - out << _lval.str; - break; - - case ELLIPSIS: - out << "..."; - break; - - case OROR: - out << "||"; - break; - - case ANDAND: - out << "&&"; - break; - - case EQCOMPARE: - out << "=="; - break; - - case NECOMPARE: - out << "!="; - break; - - case LECOMPARE: - out << "<="; - break; - - case GECOMPARE: - out << ">="; - break; - - case LSHIFT: - out << "<<"; - break; - - case RSHIFT: - out << ">>"; - break; - - case POINTSAT_STAR: - out << "->*"; - break; - - case DOT_STAR: - out << ".*"; - break; - - case UNARY_NOT: - out << "!"; - break; - - case UNARY_MINUS: - out << "-"; - break; - - case UNARY_PLUS: - out << "+"; - break; - - case UNARY_NEGATE: - out << "~"; - break; - - case UNARY_STAR: - out << "*"; - break; - - case UNARY_REF: - out << "&"; - break; - - case POINTSAT: - out << "->"; - break; - - case SCOPE: - out << "::"; - break; - - case PLUSPLUS: - out << "++"; - break; - - case MINUSMINUS: - out << "--"; - break; - - case TIMESEQUAL: - out << "*="; - break; - - case DIVIDEEQUAL: - out << "/="; - break; - - case MODEQUAL: - out << "%="; - break; - - case PLUSEQUAL: - out << "+="; - break; - - case MINUSEQUAL: - out << "-="; - break; - - case OREQUAL: - out << "|="; - break; - - case ANDEQUAL: - out << "&="; - break; - - case XOREQUAL: - out << "^="; - break; - - case LSHIFTEQUAL: - out << "<<="; - break; - - case RSHIFTEQUAL: - out << ">>="; - break; - - case ATTR_LEFT: - out << "[["; - break; - - case ATTR_RIGHT: - out << "]]"; - break; - - case KW_ALIGNAS: - out << "alignas"; - break; - - case KW_ALIGNOF: - out << "alignof"; - break; - - case KW_AUTO: - out << "auto"; - break; - - case KW_BEGIN_PUBLISH: - out << "__begin_publish"; - break; - - case KW_BLOCKING: - out << "__blocking"; - break; - - case KW_BOOL: - out << "bool"; - break; - - case KW_BUILTIN_VA_LIST: - out << "__builtin_va_list"; - break; - - case KW_CATCH: - out << "catch"; - break; - - case KW_CHAR: - out << "char"; - break; - - case KW_CHAR8_T: - out << "char8_t"; - break; - - case KW_CHAR16_T: - out << "char16_t"; - break; - - case KW_CHAR32_T: - out << "char32_t"; - break; - - case KW_CLASS: - out << "class"; - break; - - case KW_CONST: - out << "const"; - break; - - case KW_CONSTEVAL: - out << "consteval"; - break; - - case KW_CONSTEXPR: - out << "constexpr"; - break; - - case KW_CONSTINIT: - out << "constinit"; - break; - - case KW_CONST_CAST: - out << "const_cast"; - break; - - case KW_DECLTYPE: - out << "decltype"; - break; - - case KW_DEFAULT: - out << "default"; - break; - - case KW_DELETE: - out << "delete"; - break; - - case KW_DOUBLE: - out << "double"; - break; - - case KW_DYNAMIC_CAST: - out << "dynamic_cast"; - break; - - case KW_ELSE: - out << "else"; - break; - - case KW_ENUM: - out << "enum"; - break; - - case KW_EXPLICIT: - out << "explicit"; - break; - - case KW_EXPLICIT_LPAREN: - out << "explicit("; - break; - - case KW_EXTENSION: - out << "__extension"; - break; - - case KW_EXTERN: - out << "extern"; - break; - - case KW_FALSE: - out << "false"; - break; - - case KW_FINAL: - out << "final"; - break; - - case KW_FLOAT: - out << "float"; - break; - - case KW_FRIEND: - out << "friend"; - break; - - case KW_FOR: - out << "for"; - break; - - case KW_GOTO: - out << "goto"; - break; - - case KW_HAS_VIRTUAL_DESTRUCTOR: - out << "__has_virtual_destructor"; - break; - - case KW_IF: - out << "if"; - break; - - case KW_INLINE: - out << "inline"; - break; - - case KW_INT: - out << "int"; - break; - - case KW_IS_ABSTRACT: - out << "__is_abstract"; - break; - - case KW_IS_BASE_OF: - out << "__is_base_of"; - break; - - case KW_IS_CLASS: - out << "__is_class"; - break; - - case KW_IS_CONSTRUCTIBLE: - out << "__is_constructible"; - break; - - case KW_IS_CONVERTIBLE_TO: - out << "__is_convertible_to"; - break; - - case KW_IS_DESTRUCTIBLE: - out << "__is_destructible"; - break; - - case KW_IS_EMPTY: - out << "__is_empty"; - break; - - case KW_IS_ENUM: - out << "__is_enum"; - break; - - case KW_IS_FINAL: - out << "__is_final"; - break; - - case KW_IS_FUNDAMENTAL: - out << "__is_fundamental"; - break; - - case KW_IS_POD: - out << "__is_pod"; - break; - - case KW_IS_POLYMORPHIC: - out << "__is_polymorphic"; - break; - - case KW_IS_STANDARD_LAYOUT: - out << "__is_standard_layout"; - break; - - case KW_IS_TRIVIAL: - out << "__is_trivial"; - break; - - case KW_IS_TRIVIALLY_COPYABLE: - out << "__is_trivially_copyable"; - break; - - case KW_IS_UNION: - out << "__is_union"; - break; - - case KW_LONG: - out << "long"; - break; - - case KW_MAKE_MAP_KEYS_SEQ: - out << "__make_map_keys_seq"; - break; - - case KW_MAKE_MAP_PROPERTY: - out << "__make_map_property"; - break; - - case KW_MAKE_PROPERTY: - out << "__make_property"; - break; - - case KW_MAKE_PROPERTY2: - out << "__make_property2"; - break; - - case KW_MAKE_SEQ: - out << "__make_seq"; - break; - - case KW_MAKE_SEQ_PROPERTY: - out << "__make_seq_property"; - break; - - case KW_MUTABLE: - out << "mutable"; - break; - - case KW_NAMESPACE: - out << "namespace"; - break; - - case KW_NEW: - out << "new"; - break; - - case KW_NOEXCEPT: - out << "noexcept"; - break; - - case KW_NOEXCEPT_LPAREN: - out << "noexcept("; - break; - - case KW_NULLPTR: - out << "nullptr"; - break; - - case KW_OPERATOR: - if (_lval.u.identifier != nullptr) { - out << *_lval.u.identifier << "::"; - } - out << "operator"; - break; - - case KW_OVERRIDE: - out << "override"; - break; - - case KW_PRIVATE: - out << "private"; - break; - - case KW_PROTECTED: - out << "protected"; - break; - - case KW_PUBLIC: - out << "public"; - break; - - case KW_PUBLISHED: - out << "__published"; - break; - - case KW_REGISTER: - out << "register"; - break; - - case KW_REINTERPRET_CAST: - out << "reinterpret_cast"; - break; - - case KW_RESTRICT: - out << "__restrict"; - break; - - case KW_RETURN: - out << "return"; - break; - - case KW_SHORT: - out << "short"; - break; - - case KW_SIGNED: - out << "signed"; - break; - - case KW_SIZEOF: - out << "sizeof"; - break; - - case KW_STATIC: - out << "static"; - break; - - case KW_STATIC_ASSERT: - out << "static_assert"; - break; - - case KW_STATIC_CAST: - out << "static_cast"; - break; - - case KW_STRUCT: - out << "struct"; - break; - - case KW_TEMPLATE: - out << "template"; - break; - - case KW_THREAD_LOCAL: - out << "thread_local"; - break; - - case KW_THROW: - out << "throw"; - break; - - case KW_TRUE: - out << "true"; - break; - - case KW_TRY: - out << "try"; - break; - - case KW_TYPEDEF: - out << "typedef"; - break; - - case KW_TYPEID: - out << "typeid"; - break; - - case KW_TYPENAME: - out << "typename"; - break; - - case KW_UNDERLYING_TYPE: - out << "__underlying_type"; - break; - - case KW_USING: - out << "using"; - break; - - case KW_UNION: - out << "union"; - break; - - case KW_UNSIGNED: - out << "unsigned"; - break; - - case KW_VIRTUAL: - out << "virtual"; - break; - - case KW_VOID: - out << "void"; - break; - - case KW_VOLATILE: - out << "volatile"; - break; - - case KW_WCHAR_T: - out << "wchar_t"; - break; - - case KW_WHILE: - out << "while"; - break; - - case START_CPP: - case START_CONST_EXPR: - case START_TYPE: - break; - - default: - if (_token < 128 && isprint(_token)) { - out << (char)_token; - } else { - out << "\n"; - } - } -} diff --git a/dtool/src/cppparser/cppToken.h b/dtool/src/cppparser/cppToken.h deleted file mode 100644 index 89ced98800..0000000000 --- a/dtool/src/cppparser/cppToken.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppToken.h - * @author drose - * @date 1999-10-22 - */ - -#ifndef CPPTOKEN_H -#define CPPTOKEN_H - -#include "dtoolbase.h" - -#include "cppBisonDefs.h" - -/** - * - */ -class CPPToken { -public: - CPPToken(int token, int line_number = 0, int col_number = 0, - const CPPFile &file = CPPFile(""), - const std::string &str = std::string(), - const YYSTYPE &lval = YYSTYPE()); - CPPToken(int token, const YYLTYPE &loc, - const std::string &str = std::string(), - const YYSTYPE &lval = YYSTYPE()); - - static CPPToken eof(); - bool is_eof() const; - - void output(std::ostream &out) const; - void output_code(std::ostream &out) const; - - int _token; - YYSTYPE _lval; - YYLTYPE _lloc; -}; - -inline std::ostream &operator << (std::ostream &out, const CPPToken &token) { - token.output(out); - return out; -} - - -#endif diff --git a/dtool/src/cppparser/cppType.cxx b/dtool/src/cppparser/cppType.cxx deleted file mode 100644 index fcc593bbde..0000000000 --- a/dtool/src/cppparser/cppType.cxx +++ /dev/null @@ -1,535 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppType.cxx - * @author drose - * @date 1999-10-19 - */ - -#include "cppType.h" -#include "cppConstType.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" -#include "cppStructType.h" -#include "cppTypedefType.h" -#include "cppExtensionType.h" -#include - -using std::string; - -CPPType::Types CPPType::_types; -CPPType::PreferredNames CPPType::_preferred_names; -CPPType::AltNames CPPType::_alt_names; - -bool CPPTypeCompare:: -operator () (CPPType *a, CPPType *b) const { - return (*a) < (*b); -} - -/** - * - */ -CPPType:: -CPPType(const CPPFile &file) : - CPPDeclaration(file) -{ - _declaration = nullptr; - - // This is set true by interrogate when the "forcetype" keyword is used. - _forcetype = false; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPType:: -resolve_type(CPPScope *, CPPScope *) { - return this; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPType:: -is_tbd() const { - return false; -} - -/** - * Returns true if the type is considered a fundamental type. - */ -bool CPPType:: -is_fundamental() const { - return false; -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPType:: -is_standard_layout() const { - return false; -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPType:: -is_trivial() const { - return false; -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPType:: -is_trivially_copyable() const { - return false; -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPType:: -is_constructible(const CPPType *given_type) const { - return false; -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPType:: -is_default_constructible() const { - return false; -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPType:: -is_copy_constructible() const { - return false; -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPType:: -is_copy_assignable() const { - return false; -} - -/** - * Returns true if the type is destructible. - */ -bool CPPType:: -is_destructible() const { - return !is_incomplete(); -} - -/** - * Returns true if the type is a special parameter expression type. - * - * This sort of type is created to handle instance declarations that initially - * look like function prototypes. - */ -bool CPPType:: -is_parameter_expr() const { - return false; -} - -/** - * Returns true if this is an enum type, or a typedef to an enum type. - */ -bool CPPType:: -is_enum() const { - const CPPTypedefType *td_type = as_typedef_type(); - if (td_type != nullptr) { - return td_type->_type->is_enum(); - } - const CPPExtensionType *ext_type = as_extension_type(); - if (ext_type != nullptr) { - return ext_type->_type == CPPExtensionType::T_enum || - ext_type->_type == CPPExtensionType::T_enum_struct || - ext_type->_type == CPPExtensionType::T_enum_class; - } - return false; -} - -/** - * Returns true if this is a const type, or a typedef to a const type. - */ -bool CPPType:: -is_const() const { - const CPPTypedefType *td_type = as_typedef_type(); - if (td_type != nullptr) { - return td_type->_type->is_const(); - } - return get_subtype() == ST_const; -} - -/** - * Returns true if this is a reference type, or a typedef to a reference type. - */ -bool CPPType:: -is_reference() const { - const CPPTypedefType *td_type = as_typedef_type(); - if (td_type != nullptr) { - return td_type->_type->is_reference(); - } - return get_subtype() == ST_reference; -} - -/** - * Returns true if this is an unqualified or cv-qualified pointer type, or a - * typedef to one. - */ -bool CPPType:: -is_pointer() const { - const CPPTypedefType *td_type = as_typedef_type(); - if (td_type != nullptr) { - return td_type->_type->is_pointer(); - } - const CPPConstType *const_type = as_const_type(); - if (const_type != nullptr) { - return const_type->_wrapped_around->is_pointer(); - } - return get_subtype() == ST_pointer; -} - -/** - * Returns the type with any const qualifier stripped off. Will follow - * typedefs, but only if necessary. - */ -CPPType *CPPType:: -remove_const() { - const CPPTypedefType *td_type = as_typedef_type(); - if (td_type != nullptr) { - CPPType *unwrapped = td_type->_type->remove_const(); - if (unwrapped != td_type->_type) { - return unwrapped; - } else { - return this; - } - } - const CPPConstType *const_type = as_const_type(); - if (const_type != nullptr) { - return const_type->_wrapped_around->remove_const(); - } - return this; -} - -/** - * Returns the type with any reference stripped off. - */ -CPPType *CPPType:: -remove_reference() { - const CPPTypedefType *td_type = as_typedef_type(); - if (td_type != nullptr) { - CPPType *unwrapped = td_type->_type->remove_reference(); - if (unwrapped != td_type->_type) { - return unwrapped; - } else { - return this; - } - } - const CPPReferenceType *ref_type = as_reference_type(); - if (ref_type != nullptr) { - return ref_type->_pointing_at; - } - return this; -} - -/** - * Returns the type with any pointer and cv-qualifiers stripped off. - */ -CPPType *CPPType:: -remove_pointer() { - switch (get_subtype()) { - case ST_typedef: - { - const CPPTypedefType *td_type = as_typedef_type(); - CPPType *unwrapped = td_type->_type->remove_pointer(); - if (unwrapped != td_type->_type) { - return unwrapped; - } else { - return this; - } - } - - case ST_pointer: - return ((const CPPPointerType *)this)->_pointing_at; - - case ST_const: - return ((const CPPConstType *)this)->_wrapped_around->remove_pointer(); - - default: - return this; - } -} - -/** - * Returns true if the type has even been typedef'ed and therefore has a - * simple name available to stand for it. Extension types are all implicitly - * typedef'ed on declaration. - */ -bool CPPType:: -has_typedef_name() const { - return !_typedefs.empty(); -} - -/** - * Returns a string that can be used to name the type, if has_typedef_name() - * returned true. This will be the first typedef name applied to the type. - */ -string CPPType:: -get_typedef_name(CPPScope *scope) const { - if (_typedefs.empty()) { - return string(); - } else { - return _typedefs.front()->get_local_name(scope); - } -} - -/** - * Returns a fundametal one-word name for the type. This name will not - * include any scoping operators or template parameters, so it may not be a - * compilable reference to the type. - */ -string CPPType:: -get_simple_name() const { - return get_local_name(); -} - -/** - * Returns the compilable, correct name for this type within the indicated - * scope. If the scope is NULL, within the scope the type is declared in. - */ -string CPPType:: -get_local_name(CPPScope *scope) const { - std::ostringstream ostrm; - output(ostrm, 0, scope, false); - return ostrm.str(); -} - -/** - * Returns the compilable, correct name for the type, with completely explicit - * scoping. - */ -string CPPType:: -get_fully_scoped_name() const { - return get_local_name(); -} - -/** - * Returns the best name to use for the type from a programmer's point of - * view. This will typically be a typedef name if one is available, or the - * full C++ name if it is not. The typedef may or may not be visible within - * the current scope, so this type name may not be compilable. - */ -string CPPType:: -get_preferred_name() const { - string preferred_name = get_preferred_name_for(this); - if (!preferred_name.empty()) { - return preferred_name; - } - return get_local_name(); -} - -/** - * Returns the number of "alternate" names for this type. The alternate names - * are alternate typedef names. This list might be empty, or it might be - * long. One of these names may or may not be the same as the "preferred" - * name. - */ -int CPPType:: -get_num_alt_names() const { - // We do a lookup based on the type's name, instead of its pointer, so we - // can resolve different expansions of the same type. - string tname = this->get_fully_scoped_name(); - - if (!tname.empty()) { - AltNames::const_iterator ai; - ai = _alt_names.find(tname); - if (ai != _alt_names.end()) { - const Names &names = (*ai).second; - return names.size(); - } - } - - return 0; -} - -/** - * Returns the nth "alternate" name for this type. See get_num_alt_names(). - */ -string CPPType:: -get_alt_name(int n) const { - // We do a lookup based on the type's name, instead of its pointer, so we - // can resolve different expansions of the same type. - string tname = this->get_fully_scoped_name(); - - if (!tname.empty()) { - AltNames::const_iterator ai; - ai = _alt_names.find(tname); - if (ai != _alt_names.end()) { - const Names &names = (*ai).second; - if (n >= 0 && n < (int)names.size()) { - return names[n]; - } - } - } - - return string(); -} - -/** - * Returns true if the type has not yet been fully specified, false if it has. - */ -bool CPPType:: -is_incomplete() const { - return false; -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPType:: -is_equivalent(const CPPType &other) const { - if (get_subtype() != other.get_subtype()) { - return false; - } - return is_equal(&other); -} - -/** - * Returns true if variables of this type may be implicitly converted to - * the other type. - */ -bool CPPType:: -is_convertible_to(const CPPType *other) const { - return other->is_constructible(this); -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPType:: -output_instance(std::ostream &out, const string &name, CPPScope *scope) const { - output_instance(out, 0, scope, false, "", name); -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPType:: -output_instance(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, const string &prename, - const string &name) const { - output(out, indent_level, scope, complete); - out << " " << prename << name; -} - - -/** - * - */ -CPPType *CPPType:: -as_type() { - return this; -} - - -/** - * This should be called whenever a new CPPType object is created. It will - * uniquify the type pointers by checking to see if some equivalent CPPType - * object has previously been created; if it has, it returns the old object - * and deletes the new one. Otherwise, it stores the new one and returns it. - */ -CPPType *CPPType:: -new_type(CPPType *type) { - std::pair result = _types.insert(type); - if (result.second) { - // The insertion has taken place; thus, this is the first time this type - // has been declared. - assert(*result.first == type); - return type; - } - - // If this triggers, we probably messed up by defining is_less() - // incorrectly; they provide a relative ordering even though they are equal - // to each other. Or, we provided an is_equal() that gives false negatives. - assert(**result.first == *type); - - // The insertion has not taken place; thus, there was previously another - // equivalent type declared. - if (*result.first != type) { - // *** Something wrong here. Deleting this should always be safe; - // however, it's not. Thus, someone failed to call new_type() on a type - // pointer before saving it somewhere. Fix me soon. **** - - delete type; - } - return *result.first; -} - -/** - * Records a global typedef name associated with the indicated Type. This - * will be an "alt" name, and it may also become the "preferred" name. - */ -void CPPType:: -record_alt_name_for(const CPPType *type, const string &name) { - if (!name.empty()) { - string tname = type->get_fully_scoped_name(); - if (!tname.empty()) { - if (tname.find('<') != string::npos) { - // If the name contains a funny character like a template name, then - // we implicitly take the first typedef as the preferred name. - _preferred_names.insert(PreferredNames::value_type(tname, name)); - } - - Names &names = _alt_names[tname]; - if (find(names.begin(), names.end(), name) == names.end()) { - // It's not already recorded as an alt name, so record it now. - names.push_back(name); - } - } - } -} - -/** - * Returns the previously-stored "preferred" name associated with the type, if - * any, or empty string if no name is associated. - */ -string CPPType:: -get_preferred_name_for(const CPPType *type) { - // We do a lookup based on the type's name, instead of its pointer, so we - // can resolve different expansions of the same type. - string tname = type->get_fully_scoped_name(); - - if (!tname.empty()) { - PreferredNames::const_iterator pi; - pi = _preferred_names.find(tname); - if (pi != _preferred_names.end()) { - return (*pi).second; - } - } - - return string(); -} diff --git a/dtool/src/cppparser/cppType.h b/dtool/src/cppparser/cppType.h deleted file mode 100644 index d5245ac8fe..0000000000 --- a/dtool/src/cppparser/cppType.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppType.h - * @author drose - * @date 1999-10-19 - */ - -#ifndef CPPTYPE_H -#define CPPTYPE_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -#include - -class CPPType; -class CPPTypedefType; -class CPPTypeDeclaration; - - -// This is an STL function object used to uniquely order CPPType pointers. -class CPPTypeCompare { -public: - bool operator () (CPPType *a, CPPType *b) const; -}; - -/** - * - */ -class CPPType : public CPPDeclaration { -public: - typedef std::vector Typedefs; - Typedefs _typedefs; - - CPPType(const CPPFile &file); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - virtual bool is_fundamental() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - virtual bool is_destructible() const; - virtual bool is_parameter_expr() const; - - // Convenience methods. - bool is_enum() const; - bool is_const() const; - bool is_reference() const; - bool is_pointer() const; - - CPPType *remove_const(); - inline CPPType *remove_volatile() { return this; } - inline CPPType *remove_cv() { return remove_const(); }; - CPPType *remove_reference(); - CPPType *remove_pointer(); - - bool has_typedef_name() const; - std::string get_typedef_name(CPPScope *scope = nullptr) const; - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - virtual std::string get_preferred_name() const; - int get_num_alt_names() const; - std::string get_alt_name(int n) const; - - virtual bool is_incomplete() const; - virtual bool is_convertible_to(const CPPType *other) const; - virtual bool is_equivalent(const CPPType &other) const; - - void output_instance(std::ostream &out, const std::string &name, - CPPScope *scope) const; - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - - virtual CPPType *as_type(); - - - static CPPType *new_type(CPPType *type); - - static void record_alt_name_for(const CPPType *type, const std::string &name); - static std::string get_preferred_name_for(const CPPType *type); - - CPPTypeDeclaration *_declaration; - bool _forcetype; - -protected: - typedef std::set Types; - static Types _types; - - typedef std::map PreferredNames; - static PreferredNames _preferred_names; - - typedef std::vector Names; - typedef std::map AltNames; - static AltNames _alt_names; -}; - -#endif diff --git a/dtool/src/cppparser/cppTypeDeclaration.cxx b/dtool/src/cppparser/cppTypeDeclaration.cxx deleted file mode 100644 index 84b6075172..0000000000 --- a/dtool/src/cppparser/cppTypeDeclaration.cxx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypeDeclaration.cxx - * @author drose - * @date 2000-08-14 - */ - -#include "cppTypeDeclaration.h" - -/** - * Constructs a new CPPTypeDeclaration object for the given type. - */ -CPPTypeDeclaration:: -CPPTypeDeclaration(CPPType *type) : - CPPInstance(type, nullptr) -{ - assert(_type != nullptr); - if (_type->_declaration == nullptr) { - _type->_declaration = this; - } -} - -/** - * - */ -CPPDeclaration *CPPTypeDeclaration:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - CPPDeclaration *decl = - CPPInstance::substitute_decl(subst, current_scope, global_scope); - assert(decl != nullptr); - if (decl->as_type_declaration()) { - return decl; - } - assert(decl->as_instance() != nullptr); - return new CPPTypeDeclaration(decl->as_instance()->_type); -} - -/** - * - */ -void CPPTypeDeclaration:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool) const { - _type->output(out, indent_level, scope, true); -} - -/** - * - */ -CPPDeclaration::SubType CPPTypeDeclaration:: -get_subtype() const { - return ST_type_declaration; -} - -/** - * - */ -CPPTypeDeclaration *CPPTypeDeclaration:: -as_type_declaration() { - return this; -} diff --git a/dtool/src/cppparser/cppTypeDeclaration.h b/dtool/src/cppparser/cppTypeDeclaration.h deleted file mode 100644 index cd93ed0fdc..0000000000 --- a/dtool/src/cppparser/cppTypeDeclaration.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypeDeclaration.h - * @author drose - * @date 2000-08-14 - */ - -#ifndef CPPTYPEDECLARATION_H -#define CPPTYPEDECLARATION_H - -#include "dtoolbase.h" - -#include "cppInstance.h" - -/** - * A CPPTypeDeclaration is a special declaration that represents the top-level - * declaration of a type in a source file. Typically this is the first - * appearance of the type. - */ -class CPPTypeDeclaration : public CPPInstance { -public: - CPPTypeDeclaration(CPPType *type); - - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPTypeDeclaration *as_type_declaration(); -}; - -#endif diff --git a/dtool/src/cppparser/cppTypeParser.cxx b/dtool/src/cppparser/cppTypeParser.cxx deleted file mode 100644 index cdaa1d0288..0000000000 --- a/dtool/src/cppparser/cppTypeParser.cxx +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypeParser.cxx - * @author drose - * @date 1999-12-14 - */ - -#include "cppTypeParser.h" -#include "cppType.h" - -/** - * - */ -CPPTypeParser:: -CPPTypeParser(CPPScope *current_scope, CPPScope *global_scope) : - _current_scope(current_scope), - _global_scope(global_scope) -{ - _type = nullptr; -} - -/** - * - */ -CPPTypeParser:: -~CPPTypeParser() { -} - -/** - * - */ -bool CPPTypeParser:: -parse_type(const std::string &type) { - if (!init_type(type)) { - std::cerr << "Unable to parse type\n"; - return false; - } - - _type = ::parse_type(this, _current_scope, _global_scope); - - return get_error_count() == 0; -} - -/** - * - */ -bool CPPTypeParser:: -parse_type(const std::string &type, const CPPPreprocessor &filepos) { - if (!init_type(type)) { - std::cerr << "Unable to parse type\n"; - return false; - } - - copy_filepos(filepos); - - _type = ::parse_type(this, _current_scope, _global_scope); - - return get_error_count() == 0; -} - -/** - * - */ -void CPPTypeParser:: -output(std::ostream &out) const { - if (_type == nullptr) { - out << "(null type)"; - } else { - out << *_type; - } -} diff --git a/dtool/src/cppparser/cppTypeParser.h b/dtool/src/cppparser/cppTypeParser.h deleted file mode 100644 index 4064e84687..0000000000 --- a/dtool/src/cppparser/cppTypeParser.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypeParser.h - * @author drose - * @date 1999-12-14 - */ - -#ifndef CPPTYPEPARSER_H -#define CPPTYPEPARSER_H - -#include "dtoolbase.h" - -#include "cppPreprocessor.h" - -class CPPType; -class CPPScope; - -/** - * - */ -class CPPTypeParser : public CPPPreprocessor { -public: - CPPTypeParser(CPPScope *current_scope, CPPScope *global_scope); - ~CPPTypeParser(); - - bool parse_type(const std::string &type); - bool parse_type(const std::string &type, const CPPPreprocessor &filepos); - - void output(std::ostream &out) const; - - CPPScope *_current_scope; - CPPScope *_global_scope; - CPPType *_type; -}; - -inline std::ostream & -operator << (std::ostream &out, const CPPTypeParser &ep) { - ep.output(out); - return out; -} - -#endif diff --git a/dtool/src/cppparser/cppTypeProxy.cxx b/dtool/src/cppparser/cppTypeProxy.cxx deleted file mode 100644 index 4843ac5b34..0000000000 --- a/dtool/src/cppparser/cppTypeProxy.cxx +++ /dev/null @@ -1,319 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypeProxy.cxx - * @author drose - * @date 1999-12-07 - */ - -#include "cppTypeProxy.h" -#include "cppFile.h" - -using std::string; - -/** - * - */ -CPPTypeProxy:: -CPPTypeProxy() : - CPPType(CPPFile()) -{ - _actual_type = nullptr; -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPTypeProxy:: -resolve_type(CPPScope *, CPPScope *) { - if (_actual_type == nullptr) { - return this; - } - return _actual_type; -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPTypeProxy:: -is_tbd() const { - if (_actual_type == nullptr) { - return false; - } - return _actual_type->is_tbd(); -} - -/** - * Returns true if the type has even been typedef'ed and therefore has a - * simple name available to stand for it. Extension types are all implicitly - * typedef'ed on declaration. - */ -bool CPPTypeProxy:: -has_typedef_name() const { - if (_actual_type == nullptr) { - return false; - } - return _actual_type->has_typedef_name(); -} - -/** - * Returns a string that can be used to name the type, if has_typedef_name() - * returned true. This will be the first typedef name applied to the type. - */ -string CPPTypeProxy:: -get_typedef_name(CPPScope *) const { - if (_actual_type == nullptr) { - return string(); - } - return _actual_type->get_typedef_name(); -} - - -/** - * Returns a fundametal one-word name for the type. This name will not - * include any scoping operators or template parameters, so it may not be a - * compilable reference to the type. - */ -string CPPTypeProxy:: -get_simple_name() const { - if (_actual_type == nullptr) { - return "unknown"; - } - return _actual_type->get_simple_name(); -} - -/** - * Returns the compilable, correct name for this type within the indicated - * scope. If the scope is NULL, within the scope the type is declared in. - */ -string CPPTypeProxy:: -get_local_name(CPPScope *scope) const { - if (_actual_type == nullptr) { - return "unknown"; - } - return _actual_type->get_local_name(scope); -} - -/** - * Returns the compilable, correct name for the type, with completely explicit - * scoping. - */ -string CPPTypeProxy:: -get_fully_scoped_name() const { - if (_actual_type == nullptr) { - return "unknown"; - } - return _actual_type->get_fully_scoped_name(); -} - -/** - * Returns the best name to use for the type from a programmer's point of - * view. This will typically be a typedef name if one is available, or the - * full C++ name if it is not. The typedef may or may not be visible within - * the current scope, so this type name may not be compilable. - */ -string CPPTypeProxy:: -get_preferred_name() const { - if (_actual_type == nullptr) { - return "unknown"; - } - return _actual_type->get_preferred_name(); -} - -/** - * Returns true if the type has not yet been fully specified, false if it has. - */ -bool CPPTypeProxy:: -is_incomplete() const { - if (_actual_type == nullptr) { - return true; - } - return _actual_type->is_incomplete(); -} - -/** - * Formats a C++-looking line that defines an instance of the given type, with - * the indicated name. In most cases this will be "type name", but some types - * have special exceptions. - */ -void CPPTypeProxy:: -output_instance(std::ostream &out, int indent_level, CPPScope *scope, - bool complete, const string &prename, - const string &name) const { - if (_actual_type == nullptr) { - out << "unknown " << prename << name; - return; - } - _actual_type->output_instance(out, indent_level, scope, complete, - prename, name); -} - -/** - * - */ -void CPPTypeProxy:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - if (_actual_type == nullptr) { - out << "unknown"; - return; - } - _actual_type->output(out, indent_level, scope, complete); -} - - -/** - * - */ -CPPDeclaration::SubType CPPTypeProxy:: -get_subtype() const { - return ST_type_proxy; -} - -/** - * - */ -CPPType *CPPTypeProxy:: -as_type() { - if (_actual_type == nullptr) { - return this; - } - return _actual_type; -} - -/** - * - */ -CPPSimpleType *CPPTypeProxy:: -as_simple_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_simple_type(); -} - -/** - * - */ -CPPPointerType *CPPTypeProxy:: -as_pointer_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_pointer_type(); -} - -/** - * - */ -CPPReferenceType *CPPTypeProxy:: -as_reference_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_reference_type(); -} - -/** - * - */ -CPPArrayType *CPPTypeProxy:: -as_array_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_array_type(); -} - -/** - * - */ -CPPConstType *CPPTypeProxy:: -as_const_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_const_type(); -} - -/** - * - */ -CPPFunctionType *CPPTypeProxy:: -as_function_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_function_type(); -} - -/** - * - */ -CPPExtensionType *CPPTypeProxy:: -as_extension_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_extension_type(); -} - -/** - * - */ -CPPStructType *CPPTypeProxy:: -as_struct_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_struct_type(); -} - -/** - * - */ -CPPEnumType *CPPTypeProxy:: -as_enum_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_enum_type(); -} - -/** - * - */ -CPPTBDType *CPPTypeProxy:: -as_tbd_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_tbd_type(); -} - -/** - * - */ -CPPTypedefType *CPPTypeProxy:: -as_typedef_type() { - if (_actual_type == nullptr) { - return nullptr; - } - return _actual_type->as_typedef_type(); -} - -/** - * - */ -CPPTypeProxy *CPPTypeProxy:: -as_type_proxy() { - return this; -} diff --git a/dtool/src/cppparser/cppTypeProxy.h b/dtool/src/cppparser/cppTypeProxy.h deleted file mode 100644 index 87d064a3b5..0000000000 --- a/dtool/src/cppparser/cppTypeProxy.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypeProxy.h - * @author drose - * @date 1999-12-07 - */ - -#ifndef CPPTYPEPROXY_H -#define CPPTYPEPROXY_H - -#include "dtoolbase.h" - -#include "cppType.h" - -/** - * This is a special kind of type that is a placeholder for some type, - * currently unknown, that will be filled in later. It's used when a type - * that references itself must instantiate. - */ -class CPPTypeProxy : public CPPType { -public: - CPPTypeProxy(); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_tbd() const; - - bool has_typedef_name() const; - std::string get_typedef_name(CPPScope *scope = nullptr) const; - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - virtual std::string get_preferred_name() const; - - virtual bool is_incomplete() const; - - virtual void output_instance(std::ostream &out, int indent_level, - CPPScope *scope, - bool complete, const std::string &prename, - const std::string &name) const; - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - - virtual SubType get_subtype() const; - - virtual CPPType *as_type(); - virtual CPPSimpleType *as_simple_type(); - virtual CPPPointerType *as_pointer_type(); - virtual CPPReferenceType *as_reference_type(); - virtual CPPArrayType *as_array_type(); - virtual CPPConstType *as_const_type(); - virtual CPPFunctionType *as_function_type(); - virtual CPPExtensionType *as_extension_type(); - virtual CPPStructType *as_struct_type(); - virtual CPPEnumType *as_enum_type(); - virtual CPPTBDType *as_tbd_type(); - virtual CPPTypedefType *as_typedef_type(); - virtual CPPTypeProxy *as_type_proxy(); - - CPPType *_actual_type; -}; - -#endif diff --git a/dtool/src/cppparser/cppTypedefType.cxx b/dtool/src/cppparser/cppTypedefType.cxx deleted file mode 100644 index cd325d7349..0000000000 --- a/dtool/src/cppparser/cppTypedefType.cxx +++ /dev/null @@ -1,471 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypedefType.cxx - * @author rdb - * @date 2014-08-01 - */ - -#include "cppTypedefType.h" -#include "cppIdentifier.h" -#include "cppInstanceIdentifier.h" -#include "cppTemplateScope.h" -#include "indent.h" - -using std::string; - -/** - * - */ -CPPTypedefType:: -CPPTypedefType(CPPType *type, const string &name, CPPScope *current_scope) : - CPPType(CPPFile()), - _type(type), - _ident(new CPPIdentifier(name)), - _using(false) -{ - if (_ident != nullptr) { - _ident->_native_scope = current_scope; - } - - _subst_decl_recursive_protect = false; - - // assert(_type != NULL); if (global) { _type->_typedefs.push_back(this); - // CPPType::record_alt_name_for(_type, inst->get_local_name()); } -} - -/** - * - */ -CPPTypedefType:: -CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope, - CPPAttributeList attr) : - CPPType(CPPFile()), - _type(type), - _ident(ident), - _using(false) -{ - if (_ident != nullptr) { - _ident->_native_scope = current_scope; - } - _subst_decl_recursive_protect = false; - - _attributes = std::move(attr); -} - -/** - * Constructs a new CPPTypedefType object that defines a typedef to the - * indicated type according to the type and the InstanceIdentifier. The - * InstanceIdentifier pointer is deallocated. - */ -CPPTypedefType:: -CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii, - CPPScope *current_scope, const CPPFile &file) : - CPPType(file), - _using(false) -{ - assert(ii != nullptr); - _type = ii->unroll_type(type); - _ident = ii->_ident; - _attributes = std::move(ii->_attributes); - ii->_ident = nullptr; - delete ii; - - if (_ident != nullptr) { - _ident->_native_scope = current_scope; - } - - _subst_decl_recursive_protect = false; -} - -/** - * - */ -bool CPPTypedefType:: -is_scoped() const { - if (_ident == nullptr) { - return false; - } else { - return _ident->is_scoped(); - } -} - -/** - * - */ -CPPScope *CPPTypedefType:: -get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - if (_ident == nullptr) { - return current_scope; - } else { - return _ident->get_scope(current_scope, global_scope, error_sink); - } -} - -/** - * - */ -string CPPTypedefType:: -get_simple_name() const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_simple_name(); -} - -/** - * - */ -string CPPTypedefType:: -get_local_name(CPPScope *scope) const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_local_name(scope); -} - -/** - * - */ -string CPPTypedefType:: -get_fully_scoped_name() const { - if (_ident == nullptr) { - return ""; - } - return _ident->get_fully_scoped_name(); -} - -/** - * Returns true if the type has not yet been fully specified, false if it has. - */ -bool CPPTypedefType:: -is_incomplete() const { - return false; - // return _type->is_incomplete(); -} - -/** - * Returns true if the type, or any nested type within the type, is a - * CPPTBDType and thus isn't fully determined right now. In this case, - * calling resolve_type() may or may not resolve the type. - */ -bool CPPTypedefType:: -is_tbd() const { - if (_ident != nullptr && _ident->is_tbd()) { - return true; - } - return _type->is_tbd(); -} - -/** - * Returns true if the type is considered a fundamental type. - */ -bool CPPTypedefType:: -is_fundamental() const { - return _type->is_fundamental(); -} - -/** - * Returns true if the type is considered a standard layout type. - */ -bool CPPTypedefType:: -is_standard_layout() const { - return _type->is_standard_layout(); -} - -/** - * Returns true if the type is considered a Plain Old Data (POD) type. - */ -bool CPPTypedefType:: -is_trivial() const { - return _type->is_trivial(); -} - -/** - * Returns true if the type can be safely copied by memcpy or memmove. - */ -bool CPPTypedefType:: -is_trivially_copyable() const { - return _type->is_trivially_copyable(); -} - -/** - * Returns true if the type can be constructed using the given argument. - */ -bool CPPTypedefType:: -is_constructible(const CPPType *given_type) const { - return _type->is_constructible(given_type); -} - -/** - * Returns true if the type is default-constructible. - */ -bool CPPTypedefType:: -is_default_constructible() const { - return _type->is_default_constructible(); -} - -/** - * Returns true if the type is copy-constructible. - */ -bool CPPTypedefType:: -is_copy_constructible() const { - return _type->is_copy_constructible(); -} - -/** - * Returns true if the type is copy-assignable. - */ -bool CPPTypedefType:: -is_copy_assignable() const { - return _type->is_copy_assignable(); -} - -/** - * Returns true if the type is destructible. - */ -bool CPPTypedefType:: -is_destructible() const { - return _type->is_destructible(); -} - -/** - * Returns true if this declaration is an actual, factual declaration, or - * false if some part of the declaration depends on a template parameter which - * has not yet been instantiated. - */ -bool CPPTypedefType:: -is_fully_specified() const { - if (_ident != nullptr && !_ident->is_fully_specified()) { - return false; - } - return CPPDeclaration::is_fully_specified() && - _type->is_fully_specified(); -} - -/** - * - */ -CPPDeclaration *CPPTypedefType:: -instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink) const { - - return _type->instantiate(actual_params, current_scope, global_scope, error_sink); -} - -/** - * - */ -CPPDeclaration *CPPTypedefType:: -substitute_decl(CPPDeclaration::SubstDecl &subst, - CPPScope *current_scope, CPPScope *global_scope) { - - if (_ident != nullptr && _ident->get_scope(current_scope, global_scope) == global_scope) { - // Hack... I know that size_t etc is supposed to work fine, so preserve - // these top-level typedefs. - CPPDeclaration *top = - CPPType::substitute_decl(subst, current_scope, global_scope); - if (top != this) { - return top; - } - top = new CPPTypedefType(*this); - subst.insert(SubstDecl::value_type(this, top)); - return top; - } - - return _type->substitute_decl(subst, current_scope, global_scope); - - // Bah, this doesn't seem to work, and I can't figure out why. Well, for - // now, let's just substitute it with the type we're pointing to. This is - // not a huge deal for now, until we find that we need to preserve these - // typedefs. - - /* - CPPDeclaration *top = - CPPType::substitute_decl(subst, current_scope, global_scope); - if (top != this) { - return top; - } - - if (_subst_decl_recursive_protect) { - // We're already executing this block; we'll have to return a proxy to the - // type which we'll define later. - CPPTypeProxy *proxy = new CPPTypeProxy; - _proxies.push_back(proxy); - assert(proxy != NULL); - return proxy; - } - _subst_decl_recursive_protect = true; - - CPPTypedefType *rep = new CPPTypedefType(*this); - CPPDeclaration *new_type = - _type->substitute_decl(subst, current_scope, global_scope); - rep->_type = new_type->as_type(); - - if (rep->_type == NULL) { - rep->_type = _type; - } - - if (_ident != NULL) { - rep->_ident = - _ident->substitute_decl(subst, current_scope, global_scope); - } - - if (rep->_type == _type && rep->_ident == _ident) { - delete rep; - rep = this; - } - - rep = CPPType::new_type(rep)->as_typedef_type(); - subst.insert(SubstDecl::value_type(this, rep)); - - _subst_decl_recursive_protect = false; - // Now fill in all the proxies we created for our recursive references. - Proxies::iterator pi; - for (pi = _proxies.begin(); pi != _proxies.end(); ++pi) { - (*pi)->_actual_type = rep; - } - - return rep; */ -} - -/** - * If this CPPType object is a forward reference or other nonspecified - * reference to a type that might now be known a real type, returns the real - * type. Otherwise returns the type itself. - */ -CPPType *CPPTypedefType:: -resolve_type(CPPScope *current_scope, CPPScope *global_scope) { - CPPType *ptype = _type->resolve_type(current_scope, global_scope); - - if (ptype != _type) { - CPPTypedefType *rep = new CPPTypedefType(*this); - rep->_type = ptype; - return CPPType::new_type(rep); - } - - return this; -} - -/** - * Returns true if variables of this type may be implicitly converted to - * the other type. - */ -bool CPPTypedefType:: -is_convertible_to(const CPPType *other) const { - return _type->is_convertible_to(other); -} - -/** - * This is a little more forgiving than is_equal(): it returns true if the - * types appear to be referring to the same thing, even if they may have - * different pointers or somewhat different definitions. It's useful for - * parameter matching, etc. - */ -bool CPPTypedefType:: -is_equivalent(const CPPType &other) const { - CPPType *ot = (CPPType *)&other; - - // Unwrap all the typedefs to get to where it is pointing. - while (ot->get_subtype() == ST_typedef) { - ot = ot->as_typedef_type()->_type; - } - - // Compare the unwrapped type to what we are pointing to. If we are - // pointing to a typedef ourselves, then this will automatically recurse. - return _type->is_equivalent(*ot); -} - -/** - * - */ -void CPPTypedefType:: -output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const { - string name; - if (_ident != nullptr) { - name = _ident->get_local_name(scope); - } - - if (complete) { - if (_using) { - // It was declared using the "using" keyword. - if (is_template()) { - get_template_scope()->_parameters.write_formal(out, scope); - indent(out, indent_level); - } - out << "using " << name; - if (!_attributes.is_empty()) { - out << " " << _attributes; - } - out << " = "; - _type->output(out, 0, scope, false); - } else { - if (!_attributes.is_empty()) { - out << _attributes << " "; - } - out << "typedef "; - _type->output_instance(out, indent_level, scope, false, "", name); - } - } else { - out << name; - } -} - -/** - * - */ -CPPDeclaration::SubType CPPTypedefType:: -get_subtype() const { - return ST_typedef; -} - -/** - * - */ -CPPTypedefType *CPPTypedefType:: -as_typedef_type() { - return this; -} - -/** - * Called by CPPDeclaration() to determine whether this type is equivalent to - * another type of the same type. - */ -bool CPPTypedefType:: -is_equal(const CPPDeclaration *other) const { - const CPPTypedefType *ot = ((CPPDeclaration *)other)->as_typedef_type(); - assert(ot != nullptr); - - return (*_type == *ot->_type) && (*_ident == *ot->_ident) && (_using == ot->_using); -} - -/** - * Called by CPPDeclaration() to determine whether this type should be ordered - * before another type of the same type, in an arbitrary but fixed ordering. - */ -bool CPPTypedefType:: -is_less(const CPPDeclaration *other) const { - return CPPDeclaration::is_less(other); - - // The below code causes a crash for unknown reasons. - /* - const CPPTypedefType *ot = ((CPPDeclaration *)other)->as_typedef_type(); - assert(ot != NULL); - - if (_type != ot->_type) { - return _type < ot->_type; - } - - if (*_ident != *ot->_ident) { - return *_ident < *ot->_ident; - } - - return false; */ -} diff --git a/dtool/src/cppparser/cppTypedefType.h b/dtool/src/cppparser/cppTypedefType.h deleted file mode 100644 index 298505f06b..0000000000 --- a/dtool/src/cppparser/cppTypedefType.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppTypedefType.h - * @author rdb - * @date 2014-08-01 - */ - -#ifndef CPPTYPEDEFTYPE_H -#define CPPTYPEDEFTYPE_H - -#include "dtoolbase.h" -#include "cppType.h" - -class CPPIdentifier; -class CPPInstanceIdentifier; - -/** - * A type alias created by a C++ typedef or using declaration. These aren't - * officially supposed to be types in themselves, but we represent them as - * such so that we can preserve typedef names in the generated code. - */ -class CPPTypedefType : public CPPType { -public: - CPPTypedefType(CPPType *type, const std::string &name, CPPScope *current_scope); - CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope, - CPPAttributeList attr = CPPAttributeList()); - CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii, - CPPScope *current_scope, const CPPFile &file); - - bool is_scoped() const; - CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - virtual std::string get_simple_name() const; - virtual std::string get_local_name(CPPScope *scope = nullptr) const; - virtual std::string get_fully_scoped_name() const; - - virtual bool is_incomplete() const; - virtual bool is_tbd() const; - virtual bool is_fundamental() const; - virtual bool is_standard_layout() const; - virtual bool is_trivial() const; - virtual bool is_trivially_copyable() const; - virtual bool is_constructible(const CPPType *type) const; - virtual bool is_default_constructible() const; - virtual bool is_copy_constructible() const; - virtual bool is_copy_assignable() const; - virtual bool is_destructible() const; - - virtual bool is_fully_specified() const; - - virtual CPPDeclaration * - instantiate(const CPPTemplateParameterList *actual_params, - CPPScope *current_scope, CPPScope *global_scope, - CPPPreprocessor *error_sink = nullptr) const; - - virtual CPPDeclaration *substitute_decl(SubstDecl &subst, - CPPScope *current_scope, - CPPScope *global_scope); - - virtual CPPType *resolve_type(CPPScope *current_scope, - CPPScope *global_scope); - - virtual bool is_convertible_to(const CPPType *other) const; - virtual bool is_equivalent(const CPPType &other) const; - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPTypedefType *as_typedef_type(); - - CPPType *_type; - CPPIdentifier *_ident; - bool _using; - -protected: - virtual bool is_equal(const CPPDeclaration *other) const; - virtual bool is_less(const CPPDeclaration *other) const; - - bool _subst_decl_recursive_protect; - typedef std::vector Proxies; - Proxies _proxies; -}; - -#endif diff --git a/dtool/src/cppparser/cppUsing.cxx b/dtool/src/cppparser/cppUsing.cxx deleted file mode 100644 index 146f8f3f48..0000000000 --- a/dtool/src/cppparser/cppUsing.cxx +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppUsing.cxx - * @author drose - * @date 1999-11-16 - */ - -#include "cppUsing.h" -#include "cppIdentifier.h" - -/** - * - */ -CPPUsing:: -CPPUsing(CPPIdentifier *ident, bool full_namespace, const CPPFile &file) : - CPPDeclaration(file), - _ident(ident), _full_namespace(full_namespace) -{ -} - -/** - * - */ -void CPPUsing:: -output(std::ostream &out, int, CPPScope *, bool) const { - out << "using "; - if (_full_namespace) { - out << "namespace "; - } - out << *_ident; -} - -/** - * - */ -CPPDeclaration::SubType CPPUsing:: -get_subtype() const { - return ST_using; -} - -/** - * - */ -CPPUsing *CPPUsing:: -as_using() { - return this; -} diff --git a/dtool/src/cppparser/cppUsing.h b/dtool/src/cppparser/cppUsing.h deleted file mode 100644 index 13de9ce855..0000000000 --- a/dtool/src/cppparser/cppUsing.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppUsing.h - * @author drose - * @date 1999-11-16 - */ - -#ifndef CPPUSING_H -#define CPPUSING_H - -#include "dtoolbase.h" - -#include "cppDeclaration.h" - -class CPPIdentifier; -class CPPScope; - -/** - * - */ -class CPPUsing : public CPPDeclaration { -public: - CPPUsing(CPPIdentifier *ident, bool full_namespace, const CPPFile &file); - - virtual void output(std::ostream &out, int indent_level, CPPScope *scope, - bool complete) const; - virtual SubType get_subtype() const; - - virtual CPPUsing *as_using(); - - CPPIdentifier *_ident; - bool _full_namespace; -}; - -#endif diff --git a/dtool/src/cppparser/cppVisibility.cxx b/dtool/src/cppparser/cppVisibility.cxx deleted file mode 100644 index 92273c00a3..0000000000 --- a/dtool/src/cppparser/cppVisibility.cxx +++ /dev/null @@ -1,36 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppVisibility.cxx - * @author drose - * @date 1999-10-22 - */ - -#include "cppVisibility.h" - -std::ostream & -operator << (std::ostream &out, CPPVisibility vis) { - switch (vis) { - case V_published: - return out << "__published"; - - case V_public: - return out << "public"; - - case V_protected: - return out << "protected"; - - case V_private: - return out << "private"; - - case V_unknown: - return out << "unknown"; - } - - return out << "(**invalid visibility**)"; -} diff --git a/dtool/src/cppparser/cppVisibility.h b/dtool/src/cppparser/cppVisibility.h deleted file mode 100644 index 7165aaecc1..0000000000 --- a/dtool/src/cppparser/cppVisibility.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cppVisibility.h - * @author drose - * @date 1999-10-22 - */ - -#ifndef CPPVISIBILITY_H -#define CPPVISIBILITY_H - -#include "dtoolbase.h" - -enum CPPVisibility { - V_published, - V_public, - V_protected, - V_private, - V_unknown -}; - -std::ostream &operator << (std::ostream &out, CPPVisibility vis); - -#endif diff --git a/dtool/src/cppparser/p3cppParser_composite1.cxx b/dtool/src/cppparser/p3cppParser_composite1.cxx deleted file mode 100644 index 3cf2094252..0000000000 --- a/dtool/src/cppparser/p3cppParser_composite1.cxx +++ /dev/null @@ -1,26 +0,0 @@ -#include "cppAttributeList.cxx" -#include "cppFunctionType.cxx" -#include "cppGlobals.cxx" -#include "cppCommentBlock.cxx" -#include "cppClosureType.cxx" -#include "cppConstType.cxx" -#include "cppDeclaration.cxx" -#include "cppMakeProperty.cxx" -#include "cppMakeSeq.cxx" -#include "cppParameterList.cxx" -#include "cppParser.cxx" -#include "cppPointerType.cxx" -#include "cppPreprocessor.cxx" -#include "cppReferenceType.cxx" -#include "cppTemplateParameterList.cxx" -#include "cppTemplateScope.cxx" -#include "cppToken.cxx" -#include "cppType.cxx" -#include "cppTypeDeclaration.cxx" -#include "cppTypeParser.cxx" -#include "cppTypeProxy.cxx" -#include "cppTypedefType.cxx" -#include "cppSimpleType.cxx" -#include "cppTBDType.cxx" -#include "cppUsing.cxx" -#include "cppVisibility.cxx" diff --git a/dtool/src/cppparser/p3cppParser_composite2.cxx b/dtool/src/cppparser/p3cppParser_composite2.cxx deleted file mode 100644 index 1a78bd698e..0000000000 --- a/dtool/src/cppparser/p3cppParser_composite2.cxx +++ /dev/null @@ -1,17 +0,0 @@ -#include "cppArrayType.cxx" -#include "cppClassTemplateParameter.cxx" -#include "cppEnumType.cxx" -#include "cppExpression.cxx" -#include "cppExpressionParser.cxx" -#include "cppExtensionType.cxx" -#include "cppFile.cxx" -#include "cppFunctionGroup.cxx" -#include "cppIdentifier.cxx" -#include "cppInstance.cxx" -#include "cppInstanceIdentifier.cxx" -#include "cppManifest.cxx" -#include "cppNameComponent.cxx" -#include "cppNamespace.cxx" -#include "cppScope.cxx" -#include "cppStructType.cxx" - diff --git a/dtool/src/interrogate/CMakeLists.txt b/dtool/src/interrogate/CMakeLists.txt deleted file mode 100644 index 1ecba4623d..0000000000 --- a/dtool/src/interrogate/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -set(INTERROGATE_HEADERS - functionRemap.h - functionWriter.h - functionWriterPtrFromPython.h functionWriterPtrToPython.h - functionWriters.h - interfaceMaker.h - interfaceMakerC.h - interfaceMakerPython.h interfaceMakerPythonObj.h - interfaceMakerPythonSimple.h - interfaceMakerPythonNative.h - interrogate.h interrogateBuilder.h parameterRemap.I - parameterRemap.h - parameterRemapBasicStringPtrToString.h - parameterRemapBasicStringRefToString.h - parameterRemapBasicStringToString.h - parameterRemapCharStarToString.h - parameterRemapConcreteToPointer.h - parameterRemapConstToNonConst.h parameterRemapEnumToInt.h - parameterRemapPTToPointer.h - parameterRemapReferenceToConcrete.h - parameterRemapReferenceToPointer.h parameterRemapThis.h - parameterRemapToString.h - parameterRemapHandleToInt.h - parameterRemapUnchanged.h - typeManager.h -) - -set(INTERROGATE_SOURCES - functionRemap.cxx - functionWriter.cxx - functionWriterPtrFromPython.cxx functionWriterPtrToPython.cxx - functionWriters.cxx - interfaceMaker.cxx - interfaceMakerC.cxx - interfaceMakerPython.cxx interfaceMakerPythonObj.cxx - interfaceMakerPythonSimple.cxx - interfaceMakerPythonNative.cxx - interrogate.cxx interrogateBuilder.cxx parameterRemap.cxx - parameterRemapBasicStringPtrToString.cxx - parameterRemapBasicStringRefToString.cxx - parameterRemapBasicStringToString.cxx - parameterRemapCharStarToString.cxx - parameterRemapConcreteToPointer.cxx - parameterRemapConstToNonConst.cxx - parameterRemapEnumToInt.cxx parameterRemapPTToPointer.cxx - parameterRemapReferenceToConcrete.cxx - parameterRemapReferenceToPointer.cxx parameterRemapThis.cxx - parameterRemapToString.cxx - parameterRemapHandleToInt.cxx - parameterRemapUnchanged.cxx - typeManager.cxx -) - -set(INTERROGATE_PREAMBLE_PYTHON_NATIVE - ../interrogatedb/py_panda.cxx - ../interrogatedb/py_compat.cxx - ../interrogatedb/py_wrappers.cxx - ../interrogatedb/dtool_super_base.cxx -) - -composite_sources(interrogate INTERROGATE_SOURCES) -add_executable(interrogate ${INTERROGATE_HEADERS} ${INTERROGATE_SOURCES}) -target_link_libraries(interrogate p3cppParser p3interrogatedb - PKG::OPENSSL) - -# Python preamble for interrogate_module -set(_preamble_files) -foreach(_file ${INTERROGATE_PREAMBLE_PYTHON_NATIVE}) - # Resolve symlinks, use absolute path, and add a `#line 1 ...` directive - get_filename_component(_file "${_file}" REALPATH) - - string(SHA1 _hash "${_file}") - set(_line_file "${CMAKE_CURRENT_BINARY_DIR}/.${_hash}.h") - file(WRITE "${_line_file}" "#line 1 \"${_file}\"\n") - - list(APPEND _preamble_files "${_line_file}") - list(APPEND _preamble_files "${_file}") -endforeach(_file) - -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx - COMMAND ${CMAKE_COMMAND} - -D OUTPUT_FILE="${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx" - -D INPUT_FILES="${_preamble_files}" - -D SYMBOL_NAME="interrogate_preamble_python_native" - -P ${PROJECT_SOURCE_DIR}/cmake/scripts/ConcatenateToCXX.cmake - DEPENDS ${INTERROGATE_PREAMBLE_PYTHON_NATIVE} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") - -add_executable(interrogate_module interrogate_module.cxx - ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx) -target_link_libraries(interrogate_module p3cppParser p3interrogatedb - PKG::OPENSSL) - -if(NOT CMAKE_CROSSCOMPILING) - add_executable(host_interrogate ALIAS interrogate) - add_executable(host_interrogate_module ALIAS interrogate_module) - -else() - # When cross-compiling, we must find the host Interrogate. - # TODO: We should also try to find_package(Panda3D ...) before falling back - # to searching manually. - find_program(HOST_PATH_INTERROGATE interrogate) - find_program(HOST_PATH_INTERROGATE_MODULE interrogate_module) - - add_executable(host_interrogate IMPORTED GLOBAL) - if(HOST_PATH_INTERROGATE) - set_target_properties(host_interrogate PROPERTIES - IMPORTED_LOCATION "${HOST_PATH_INTERROGATE}") - endif() - - add_executable(host_interrogate_module IMPORTED GLOBAL) - if(HOST_PATH_INTERROGATE_MODULE) - set_target_properties(host_interrogate_module PROPERTIES - IMPORTED_LOCATION "${HOST_PATH_INTERROGATE_MODULE}") - endif() - -endif() - -if(WANT_INTERROGATE) - install(TARGETS interrogate interrogate_module EXPORT Core COMPONENT CoreDevel DESTINATION ${CMAKE_INSTALL_BINDIR}) - install(FILES ${INTERROGATE_HEADERS} COMPONENT CoreDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) - -else() - set_target_properties(interrogate interrogate_module - PROPERTIES EXCLUDE_FROM_ALL ON) - -endif() diff --git a/dtool/src/interrogate/README.md b/dtool/src/interrogate/README.md deleted file mode 100644 index 4da044c8b5..0000000000 --- a/dtool/src/interrogate/README.md +++ /dev/null @@ -1,28 +0,0 @@ -A key advantage of Panda3D is that it provides developers with the -ability to use both C++ and Python simultaneously. Essentially, Panda3D -gives programmers the best of both worlds, as they are able to take -advantage of the high performance and low-level programming found in -C++ in addition to the flexibility, interactive scripting, and -rapid-prototyping capabilities of Python. This feature is made possible -due to Python’s ability to call C libraries, and ultimately make use of -Panda3D’s Interrogate System: an automated C++ Extension Module -generation utility similar to SWIG. Although Python is the favored -scripting language of Panda3D, the engine is highly extensible in this -aspect, as any language that has a foreign function interface can make -use of the Interrogate System. - -The Interrogate System works like a compiler by scanning and parsing -C++ code for the Panda3D-specific, “PUBLISHED” keyword. This keyword -marks the particular methods of a class that are to be exposed within a -C++ Extension Module for that class which is eventually generated. One -benefit of using the “PUBLISHED” keyword is that it alleviates the need -for an interface file that provides function prototypes for the class -methods that will be exposed within the extension module, as is the -case with SWIG. Interrogate turns a class into a loose collection of -Python interface wrapper functions that make up the C++ Extension -Module. - -This package depends on the 'cppparser' package, which contains the -code that parses the C++ headers, and the 'interrogatedb' package, -which contains the intermediate representation of the interfaces that -can be saved to a database file for FFI generation tools to consume. diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx deleted file mode 100644 index b692577067..0000000000 --- a/dtool/src/interrogate/functionRemap.cxx +++ /dev/null @@ -1,1030 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionRemap.cxx - * @author drose - * @date 2001-09-19 - */ - -#include "functionRemap.h" -#include "typeManager.h" -#include "interrogate.h" -#include "parameterRemap.h" -#include "parameterRemapThis.h" -#include "parameterRemapHandleToInt.h" -#include "parameterRemapUnchanged.h" -#include "interfaceMaker.h" -#include "interrogateBuilder.h" - -#include "interrogateDatabase.h" -#include "cppExpression.h" -#include "cppInstance.h" -#include "cppArrayType.h" -#include "cppConstType.h" -#include "cppFunctionType.h" -#include "cppParameterList.h" -#include "cppReferenceType.h" -#include "interrogateType.h" -#include "pnotify.h" - -using std::ostream; -using std::ostringstream; -using std::string; - -/** - * - */ -FunctionRemap:: -FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc, - CPPInstance *cppfunc, int num_default_parameters, - InterfaceMaker *interface_maker) { - _return_type = nullptr; - _void_return = true; - _ForcedVoidReturn = false; - _has_this = false; - _blocking = false; - _extension = false; - _const_method = false; - _first_true_parameter = 0; - _num_default_parameters = num_default_parameters; - _type = T_normal; - _flags = 0; - _args_type = 0; - _wrapper_index = 0; - - _return_value_needs_management = false; - _return_value_destructor = 0; - _manage_reference_count = false; - - _cppfunc = cppfunc; - _ftype = _cppfunc->_type->as_function_type(); - _cpptype = itype._cpptype; - _cppscope = itype._cppscope; - - _is_valid = setup_properties(ifunc, interface_maker); -} - -/** - * - */ -FunctionRemap:: -~FunctionRemap() { -} - -/** - * Returns a string that will be a suitable name for the nth parameter in the - * generated code. This may not correspond to the name of the parameter in - * the original code. - */ -string FunctionRemap:: -get_parameter_name(int n) const { - ostringstream str; - str << "param" << n; - return str.str(); -} - -/** - * Writes a sequence of commands to the given output stream to call the - * wrapped function. The parameter values are assumed to be simply the names - * of the parameters. - * - * The return value is the expression to return, if we are returning a value, - * or the empty string if we return nothing. - */ -string FunctionRemap:: -call_function(ostream &out, int indent_level, bool convert_result, - const string &container) const { - vector_string pexprs; - for (size_t i = 0; i < _parameters.size(); ++i) { - pexprs.push_back(get_parameter_name(i)); - } - return call_function(out, indent_level, convert_result, container, pexprs); -} - -/** - * Writes a sequence of commands to the given output stream to call the - * wrapped function. The parameter values are taken from pexprs. - * - * The return value is the expression to return, if we are returning a value, - * or the empty string if we return nothing. - */ -string FunctionRemap:: -call_function(ostream &out, int indent_level, bool convert_result, - const string &container, const vector_string &pexprs) const { - string return_expr; - - if (_type == T_destructor) { - // A destructor wrapper is just a wrapper around the delete operator. - assert(!container.empty()); - assert(_cpptype != nullptr); - - if (TypeManager::is_reference_count(_cpptype)) { - // Except for a reference-count type object, in which case the - // destructor is a wrapper around unref_delete(). - InterfaceMaker::indent(out, indent_level) - << "unref_delete(" << container << ");\n"; - } else { - InterfaceMaker::indent(out, indent_level) << "delete " << container << ";\n"; - } - - } else if (_type == T_typecast_method) { - // A typecast method can be invoked implicitly. - ostringstream cast_expr; - cast_expr << "(" - << _return_type->get_orig_type()->get_local_name(&parser) << ")"; - - _parameters[0]._remap->pass_parameter(cast_expr, container); - - if (!convert_result) { - return_expr = cast_expr.str(); - } else { - string new_str = - _return_type->prepare_return_expr(out, indent_level, cast_expr.str()); - return_expr = _return_type->get_return_expr(new_str); - } - - } else if (_type == T_typecast) { - // A regular typecast converts from a pointer type to another pointer - // type. (This is different from the typecast method, above, which - // converts from the concrete type to some other type.) - assert(!container.empty()); - string cast_expr = - "(" + _return_type->get_orig_type()->get_local_name(&parser) + - ")" + container; - - if (!convert_result) { - return_expr = cast_expr; - } else { - string new_str = - _return_type->prepare_return_expr(out, indent_level, cast_expr); - return_expr = _return_type->get_return_expr(new_str); - } - - } else if (_type == T_constructor) { - // A special case for constructors. - if (_extension) { - // Extension constructors are a special case. We assume there is a - // default constructor for the class, and the actual construction is - // done by an __init__ method. - InterfaceMaker::indent(out, indent_level); - _return_type->get_new_type()->output_instance(out, "result", &parser); - out << " = new " << _cpptype->get_local_name(&parser) << ";\n"; - - InterfaceMaker::indent(out, indent_level) - << get_call_str("result", pexprs) << ";\n"; - - return_expr = "result"; - - } else { - string defconstruct = builder.in_defconstruct(_cpptype->get_local_name(&parser)); - string call_expr; - - if (pexprs.empty() && !defconstruct.empty()) { - call_expr = defconstruct; - } else { - call_expr = get_call_str(container, pexprs); - } - - if (!_return_type->return_value_needs_management()) { - return_expr = _return_type->get_return_expr(call_expr); - } else { - return_expr = "new " + call_expr; - } - } - if (_void_return) { - nout << "Error, constructor for " << *_cpptype << " returning void.\n"; - return_expr = ""; - } - - } else if (_type == T_assignment_method) { - // Another special case for assignment operators. - assert(!container.empty()); - InterfaceMaker::indent(out, indent_level) - << get_call_str(container, pexprs) << ";\n"; - - string this_expr = container; - string ref_expr = "*" + this_expr; - - if (!convert_result) { - return_expr = ref_expr; - } else { - string new_str = - _return_type->prepare_return_expr(out, indent_level, ref_expr); - return_expr = _return_type->get_return_expr(new_str); - - // Now a simple special-case test. Often, we will have converted the - // reference-returning assignment operator to a pointer. In this case, - // we might inadvertently generate code like "return &(*this)", when - // "return this" would do. We check for this here and undo it as a - // special case. - - // There's no real good reason to do this, other than that it feels more - // satisfying to a casual perusal of the generated code. It *is* - // conceivable that some broken compilers wouldn't like "&(*this)", - // though. - - if (return_expr == "&(" + ref_expr + ")" || - return_expr == "&" + ref_expr) { - return_expr = this_expr; - } - } - - } else if (_void_return) { - InterfaceMaker::indent(out, indent_level) - << get_call_str(container, pexprs) << ";\n"; - - } else { - string call = get_call_str(container, pexprs); - - if (!convert_result) { - return_expr = call; - - } else { - // if (_return_type->return_value_should_be_simple()) { - if (false) { - // We have to assign the result to a temporary first; this makes it a - // bit easier on poor old VC++. - InterfaceMaker::indent(out, indent_level); - _return_type->get_orig_type()->output_instance(out, "result", - &parser); - out << " = " << call << ";\n"; - - // Use of the C++11 std::move function basically turns an lvalue into - // an rvalue, allowing a move constructor to be called instead of a - // copy constructor (since we won't be using the return value any - // more), which is usually more efficient if it exists. If it - // doesn't, it shouldn't do any harm. - string new_str = - _return_type->prepare_return_expr(out, indent_level, "std::move(result)"); - return_expr = _return_type->get_return_expr(new_str); - - } else { - // This should be simple enough that we can return it directly. - string new_str = - _return_type->prepare_return_expr(out, indent_level, call); - return_expr = _return_type->get_return_expr(new_str); - } - } - } - - return return_expr; -} - -/** - * Writes a line describing the original C++ method or function. This is - * generally useful only within a comment. - */ -void FunctionRemap:: -write_orig_prototype(ostream &out, int indent_level, bool local, int num_default_args) const { - if (local) { - _cppfunc->output(out, indent_level, nullptr, false, num_default_args); - } else { - _cppfunc->output(out, indent_level, &parser, false, num_default_args); - } -} - -/** - * Creates an InterrogateFunctionWrapper object corresponding to this callable - * instance and stores it in the database. - */ -FunctionWrapperIndex FunctionRemap:: -make_wrapper_entry(FunctionIndex function_index) { - _wrapper_index = - InterrogateDatabase::get_ptr()->get_next_index(); - - InterrogateFunctionWrapper iwrapper; - iwrapper._function = function_index; - iwrapper._name = _wrapper_name; - iwrapper._unique_name = _unique_name; - - if (_cppfunc->_leading_comment != nullptr) { - iwrapper._comment = InterrogateBuilder::trim_blanks(_cppfunc->_leading_comment->_comment); - } - - if (output_function_names) { - // If we're keeping the function names, record that the wrapper is - // callable. - iwrapper._flags |= InterrogateFunctionWrapper::F_callable_by_name; - } - - if (_flags & F_copy_constructor) { - iwrapper._flags |= InterrogateFunctionWrapper::F_copy_constructor; - } - - if (_flags & F_coerce_constructor) { - iwrapper._flags |= InterrogateFunctionWrapper::F_coerce_constructor; - } - - if (_extension) { - iwrapper._flags |= InterrogateFunctionWrapper::F_extension; - } - - if (_cppfunc->_attributes.has_attribute("deprecated")) { - iwrapper._flags |= InterrogateFunctionWrapper::F_deprecated; - } - - Parameters::const_iterator pi; - for (pi = _parameters.begin(); - pi != _parameters.end(); - ++pi) { - InterrogateFunctionWrapper::Parameter param; - param._parameter_flags = 0; - if ((*pi)._remap->new_type_is_atomic_string()) { - param._type = builder.get_atomic_string_type(); - } else { - param._type = builder.get_type((*pi)._remap->get_new_type(), false); - } - param._name = (*pi)._name; - if ((*pi)._has_name) { - param._parameter_flags |= InterrogateFunctionWrapper::PF_has_name; - } - if ((*pi)._remap->has_default_value()) { - param._parameter_flags |= InterrogateFunctionWrapper::PF_is_optional; - } - iwrapper._parameters.push_back(param); - } - - if (_has_this) { - // If one of the parameters is "this", it must be the first one. - assert(!iwrapper._parameters.empty()); - iwrapper._parameters.front()._parameter_flags |= - InterrogateFunctionWrapper::PF_is_this; - } - - if (!_void_return) { - iwrapper._flags |= InterrogateFunctionWrapper::F_has_return; - } - - if (_return_type->new_type_is_atomic_string()) { - iwrapper._return_type = builder.get_atomic_string_type(); - } else { - iwrapper._return_type = - builder.get_type(_return_type->get_new_type(), false); - } - - if (_return_value_needs_management) { - iwrapper._flags |= InterrogateFunctionWrapper::F_caller_manages; - FunctionIndex destructor = _return_value_destructor; - - if (destructor != 0) { - iwrapper._return_value_destructor = destructor; - - } else { - // We don't need to report this warning, since the FFI code understands - // that if the destructor function is zero, it should use the regular - // class destructor. - - // nout << "Warning! Destructor for " << *_return_type->get_orig_type() - // << " is unavailable.\n" << " Cannot manage return value for:\n " << - // description << "\n"; - } - } - - InterrogateDatabase::get_ptr()->add_wrapper(_wrapper_index, iwrapper); - return _wrapper_index; -} - -/** - * Returns a string suitable for calling the wrapped function. If pexprs is - * nonempty, it represents the list of expressions that will evaluate to each - * parameter value. - */ -string FunctionRemap:: -get_call_str(const string &container, const vector_string &pexprs) const { - // Build up the call to the actual function. - ostringstream call; - - // Getters and setters are a special case. - if (_type == T_getter) { - if (_has_this && !container.empty()) { - call << "(" << container << ")->" << _expression; - } else { - call << _expression; - } - - } else if (_type == T_setter) { - string expr; - if (_has_this && !container.empty()) { - expr = "(" + container + ")->" + _expression; - } else { - expr = _expression; - } - - // It's not possible to assign arrays in C++, we have to copy them. - bool paren_close = false; - CPPType *param_type = _parameters[_first_true_parameter]._remap->get_orig_type(); - CPPArrayType *array_type = param_type->as_array_type(); - if (array_type != nullptr) { - call << "std::copy(" << expr << ", " << expr << " + " << *array_type->_bounds << ", "; - paren_close = true; - } - else if (TypeManager::is_pointer_to_PyObject(param_type)) { - call << "Dtool_Assign_PyObject(" << expr << ", "; - paren_close = true; - } - else { - call << expr << " = "; - } - - _parameters[_first_true_parameter]._remap->pass_parameter(call, - get_parameter_expr(_first_true_parameter, pexprs)); - - if (paren_close) { - call << ')'; - } - - } else if (_type == T_item_assignment_operator) { - call << "("; - _parameters[0]._remap->pass_parameter(call, container); - call << ")["; - - size_t pn = _first_true_parameter; - _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs)); - call << "] = "; - ++pn; - _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs)); - - } else { - // If this function is marked as having an extension function, call that - // instead. - if (_extension) { - if (!container.empty()) { - call << "invoke_extension(" << container << ")."; - } else { - call << "Extension<" << _cpptype->get_local_name(&parser) << ">::"; - } - - if (_type == T_constructor) { - // Constructor extensions are named __init__, by convention. - call << "__init__"; - } else { - call << _cppfunc->get_local_name(); - } - } else { - if (_type == T_constructor) { - // Constructors are called differently. - call << _cpptype->get_local_name(&parser); - - } else if (_has_this && !container.empty()) { - // If we have a "this" parameter, the calling convention is also a bit - // different. - call << "(("; - _parameters[0]._remap->pass_parameter(call, container); - call << ")." << _cppfunc->get_local_name() << ")"; - - } else { - call << "("; - if (_cpptype != nullptr) { - call << _cpptype->get_local_name(&parser); - } - call << "::" << _cppfunc->get_local_name() << ")"; - } - } - call << "("; - write_call_args(call, pexprs); - call << ")"; - } - - return call.str(); -} - -/** - * Writes the arguments to pass to the function. - */ -void FunctionRemap:: -write_call_args(std::ostream &call, const vector_string &pexprs) const { - const char *separator = ""; - if (_flags & F_explicit_self) { - // Pass on the PyObject * that we stripped off above. - call << separator << "self"; - separator = ", "; - } - if (_flags & F_explicit_cls) { - call << separator << "cls"; - separator = ", "; - } - - size_t pn; - size_t num_parameters = pexprs.size(); - - for (pn = _first_true_parameter; - pn < num_parameters; ++pn) { - nassertd(pn < _parameters.size()) break; - call << separator; - _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs)); - separator = ", "; - } -} - -/** - * Returns the minimum number of arguments that needs to be passed to this - * function. - */ -int FunctionRemap:: -get_min_num_args() const { - int min_num_args = 0; - Parameters::const_iterator pi; - pi = _parameters.begin(); - if (_has_this && pi != _parameters.end()) { - ++pi; - } - for (; pi != _parameters.end(); ++pi) { - ParameterRemap *param = (*pi)._remap; - if (param->get_default_value() != nullptr) { - // We've reached the first parameter that takes a default value. - break; - } else { - ++min_num_args; - } - } - return min_num_args; -} - -/** - * Returns the maximum number of arguments that can be passed to this - * function. - */ -int FunctionRemap:: -get_max_num_args() const { - int max_num_args = _parameters.size(); - if (_has_this && _type != FunctionRemap::T_constructor) { - --max_num_args; - } - return max_num_args; -} - -/** - * Returns a string that represents the expression associated with the nth - * parameter. This is just the nth element of pexprs if it is nonempty, or - * the name of the nth parameter is it is empty. - */ -string FunctionRemap:: -get_parameter_expr(size_t n, const vector_string &pexprs) const { - if (n < pexprs.size()) { - return pexprs[n]; - } - return get_parameter_name(n); -} - -/** - * Sets up the properties of the function appropriately. Returns true if - * successful, or false if there is something unacceptable about the function. - */ -bool FunctionRemap:: -setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_maker) { - _function_signature = - TypeManager::get_function_signature(_cppfunc, _num_default_parameters); - _expression = ifunc._expression; - - if ((_ftype->_flags & CPPFunctionType::F_constructor) != 0) { - _type = T_constructor; - - } else if ((_ftype->_flags & CPPFunctionType::F_destructor) != 0) { - _type = T_destructor; - - } else if ((_ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) { - _type = T_typecast_method; - - } else if ((ifunc._flags & InterrogateFunction::F_typecast) != 0) { - _type = T_typecast; - - } else if ((ifunc._flags & InterrogateFunction::F_getter) != 0) { - _type = T_getter; - - } else if ((ifunc._flags & InterrogateFunction::F_setter) != 0) { - _type = T_setter; - - } else if ((ifunc._flags & InterrogateFunction::F_item_assignment) != 0) { - _type = T_item_assignment_operator; - } - - if ((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0) { - // If it's marked as a "blocking" method or function, record that. - _blocking = true; - } - if ((_cppfunc->_storage_class & CPPInstance::SC_extension) != 0) { - // Same with functions or methods marked with "extension". - _extension = true; - } - - string fname = _cppfunc->get_simple_name(); - CPPType *rtype = _ftype->_return_type->resolve_type(&parser, _cppscope); - - if (_cpptype != nullptr && - ((_cppfunc->_storage_class & CPPInstance::SC_static) == 0) && - _type != T_constructor) { - - // If this is a method, but not a static method, and not a constructor, - // then we need a "this" parameter. - _has_this = true; - _const_method = (_ftype->_flags & CPPFunctionType::F_const_method) != 0; - - if (interface_maker->synthesize_this_parameter()) { - // If the interface_maker demands it, the "this" parameter is treated as - // any other parameter, and inserted at the beginning of the parameter - // list. - Parameter param; - param._name = "this"; - param._has_name = true; - if (_const_method) { - CPPType *const_type = CPPType::new_type(new CPPConstType(_cpptype)); - param._remap = interface_maker->remap_parameter(_cpptype, const_type); - } else { - param._remap = interface_maker->remap_parameter(_cpptype, _cpptype); - } - // param._remap = new ParameterRemapThis(_cpptype, _const_method); - _parameters.push_back(param); - _first_true_parameter = 1; - } - - // Also check the name of the function. If it's one of the assignment- - // style operators, flag it as such. - if (fname == "operator =" || - fname == "operator *=" || - fname == "operator /=" || - fname == "operator %=" || - fname == "operator +=" || - fname == "operator -=" || - fname == "operator |=" || - fname == "operator &=" || - fname == "operator ^=" || - fname == "operator <<=" || - fname == "operator >>=") { - _type = T_assignment_method; - } - } - - const CPPParameterList::Parameters ¶ms = - _ftype->_parameters->_parameters; - for (int i = 0; i < (int)params.size() - _num_default_parameters; i++) { - // CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope); - CPPType *type = params[i]->_type; - Parameter param; - param._has_name = true; - param._name = params[i]->get_simple_name(); - - if (param._name.empty()) { - // If the parameter has no name, record it as being nameless, but also - // synthesize one in case someone asks anyway. - param._has_name = false; - ostringstream param_name; - param_name << "param" << i; - param._name = param_name.str(); - } - - param._remap = interface_maker->remap_parameter(_cpptype, type); - if (param._remap == nullptr) { - // If we can't handle one of the parameter types, we can't call the - // function. - if (fname == "__traverse__") { - // Hack to record this even though we can't wrap visitproc. - param._remap = new ParameterRemapUnchanged(type); - } else { - // nout << "Can't handle parameter " << i << " of method " << - // *_cppfunc << "\n"; - return false; - } - } else { - param._remap->set_default_value(params[i]->_initializer); - } - - if (!param._remap->is_valid()) { - nout << "Invalid remap for parameter " << i << " of method " << *_cppfunc << "\n"; - return false; - } - - _parameters.push_back(param); - } - - if (_type == T_constructor) { - // Constructors are a special case. These appear to return void as seen - // by the parser, but we know they actually return a new concrete - // instance. - - if (_cpptype == nullptr) { - nout << "Method " << *_cppfunc << " has no struct type\n"; - return false; - } - - _return_type = interface_maker->remap_parameter(_cpptype, _cpptype); - if (_return_type != nullptr) { - _void_return = false; - } - - } else if (_type == T_assignment_method) { - // Assignment-type methods are also a special case. We munge these to - // return *this, which is a semi-standard C++ convention anyway. We just - // enforce it. - - if (_cpptype == nullptr) { - nout << "Method " << *_cppfunc << " has no struct type\n"; - return false; - } else { - CPPType *ref_type = CPPType::new_type(new CPPReferenceType(_cpptype)); - _return_type = interface_maker->remap_parameter(_cpptype, ref_type); - if (_return_type != nullptr) { - _void_return = false; - } - } - - } else if (fname == "operator <=>") { - // This returns an opaque object that we must leave unchanged. - _return_type = new ParameterRemapUnchanged(rtype); - _void_return = false; - - } else { - // The normal case. - _return_type = interface_maker->remap_parameter(_cpptype, rtype); - if (_return_type != nullptr) { - _void_return = TypeManager::is_void(rtype); - } - } - - if (_return_type == nullptr || - !_return_type->is_valid()) { - // If our return type isn't something we can deal with, treat the function - // as if it returns NULL. - _void_return = true; - _ForcedVoidReturn = true; - CPPType *void_type = TypeManager::get_void_type(); - _return_type = interface_maker->remap_parameter(_cpptype, void_type); - assert(_return_type != nullptr); - } - - // Do we need to manage the return value? - _return_value_needs_management = - _return_type->return_value_needs_management(); - _return_value_destructor = - _return_type->get_return_value_destructor(); - - // Should we manage a reference count? - CPPType *return_type = _return_type->get_new_type(); - return_type = TypeManager::resolve_type(return_type, _cppscope); - CPPType *return_meat_type = TypeManager::unwrap_pointer(return_type); - - if (manage_reference_counts && - TypeManager::is_reference_count_pointer(return_type) && - !TypeManager::has_protected_destructor(return_meat_type)) { - // Yes! - _manage_reference_count = true; - _return_value_needs_management = true; - - // This is problematic, because we might not have the class in question - // fully defined here, particularly if the class is defined in some other - // library. - _return_value_destructor = builder.get_destructor_for(return_meat_type); - } - - if (_type == T_getter && TypeManager::is_pointer_to_PyObject(return_type)) { - _manage_reference_count = true; - _return_value_needs_management = true; - } - - // Check for a special meaning by name and signature. - size_t first_param = 0; - if (_has_this) { - first_param = 1; - } - - if (_parameters.size() > first_param && - TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) { - // Here's a special case. If the first parameter of a nonstatic method - // is a PyObject * called "self", then we will automatically fill it in - // from the this pointer, and remove it from the generated parameter list. - // For static methods, we offer "cls" instead, containing the type object. - if (_parameters[first_param]._name == "self") { - _parameters.erase(_parameters.begin() + first_param); - _flags |= F_explicit_self; - } - else if (!_has_this && _parameters[first_param]._name == "cls") { - _parameters.erase(_parameters.begin() + first_param); - _flags |= F_explicit_cls; - } - } - - if (_parameters.size() == first_param) { - _args_type = InterfaceMaker::AT_no_args; - } else if (_parameters.size() == first_param + 1 && - _parameters[first_param]._remap->get_default_value() == nullptr) { - _args_type = InterfaceMaker::AT_single_arg; - } else { - _args_type = InterfaceMaker::AT_varargs; - - // If the arguments are named "args" and "kwargs", we will be directly - // passing the argument tuples to the function. - if (_parameters.size() == first_param + 2 && - _parameters[first_param]._name == "args" && - (_parameters[first_param + 1]._name == "kwargs" || - _parameters[first_param + 1]._name == "kwds")) { - _flags |= F_explicit_args; - _args_type = InterfaceMaker::AT_keyword_args; - } - } - - switch (_type) { - case T_normal: - if (fname == "operator []" || fname == "__getitem__") { - _flags |= F_getitem; - if (_has_this && _parameters.size() == 2) { - if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { - // It receives a single int parameter. - _flags |= F_getitem_int; - } - } - - } else if (fname == "__setitem__") { - if (_has_this && _parameters.size() > 2) { - _flags |= F_setitem; - if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { - // Its first parameter is an int parameter, presumably an index. - _flags |= F_setitem_int; - _args_type = InterfaceMaker::AT_varargs; - } - } - - } else if (fname == "__delitem__") { - if (_has_this && _parameters.size() == 2) { - _flags |= F_delitem; - if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { - // Its first parameter is an int parameter, presumably an index. - _flags |= F_delitem_int; - _args_type = InterfaceMaker::AT_single_arg; - } - } - - } else if (fname == "size" || fname == "__len__") { - if (_parameters.size() == first_param && - TypeManager::is_integer(_return_type->get_new_type())) { - // It receives no parameters, and returns an integer. - _flags |= F_size; - } - - } else if (fname == "make_copy") { - if (_has_this && _parameters.size() == 1 && - TypeManager::is_pointer(_return_type->get_new_type())) { - // It receives no parameters, and returns a pointer. - _flags |= F_make_copy; - } - - } else if (fname == "__iter__") { - if (_parameters.size() == first_param && - TypeManager::is_pointer(_return_type->get_new_type())) { - // It receives no parameters, and returns a pointer. - _flags |= F_iter; - } - - } else if (fname == "compare_to") { - if (_has_this && _parameters.size() == 2 && - TypeManager::is_integer(_return_type->get_new_type())) { - // It receives one parameter, and returns an integer. - _flags |= F_compare_to; - } - - } else if (fname == "make") { - if (!_has_this && _parameters.size() >= 1 && - TypeManager::is_pointer(_return_type->get_new_type())) { - // We can use this for coercion, except if this is a kwargs param that - // does not have a default value. - if ((_flags & F_explicit_args) == 0 || - _parameters.size() != first_param + 2 || - _parameters[first_param + 1]._remap->has_default_value()) { - _flags |= F_coerce_constructor; - } - } - - if (_args_type == InterfaceMaker::AT_varargs) { - // Of course methods named "make" can still take kwargs, if they are - // named. - for (size_t i = first_param; i < _parameters.size(); ++i) { - if (_parameters[i]._has_name) { - _args_type = InterfaceMaker::AT_keyword_args; - break; - } - } - } - - } else if (fname == "operator /") { - if (_has_this && _parameters.size() == 2 && - TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { - // This division operator takes a single integer argument. - _flags |= F_divide_integer; - } - - } else if (fname == "get_key" || fname == "get_hash") { - if (_has_this && _parameters.size() == 1 && - TypeManager::is_integer(_return_type->get_new_type())) { - _flags |= F_hash; - } - - } else if (fname == "operator ()" || fname == "__call__") { - // Call operators always take keyword arguments. - _args_type = InterfaceMaker::AT_keyword_args; - - } else if (fname == "__setattr__" - || fname == "__getattr__" - || fname == "__delattr__") { - // Just to prevent these from getting keyword arguments. - - } else if (fname == "__setstate__") { - _args_type = InterfaceMaker::AT_single_arg; - - } else { - if (_args_type == InterfaceMaker::AT_varargs) { - // Every other method can take keyword arguments, if they take more - // than one argument, and the arguments are named. - for (size_t i = first_param; i < _parameters.size(); ++i) { - if (_parameters[i]._has_name) { - _args_type |= InterfaceMaker::AT_keyword_args; - break; - } - } - } else if (_args_type == InterfaceMaker::AT_single_arg) { - // If it takes an argument named "args", we are directly passing the - // "args" tuple to the function. - if (_parameters[first_param]._name == "args") { - _flags |= F_explicit_args; - _args_type = InterfaceMaker::AT_varargs; - } - } - } - break; - - case T_assignment_method: - if (fname == "operator /=") { - if (_has_this && _parameters.size() == 2 && - TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { - // This division operator takes a single integer argument. - _flags |= F_divide_integer; - } - } - break; - - case T_item_assignment_operator: - // The concept of "item assignment operator" doesn't really exist in C++, - // but it does in scripting languages, and this allows us to wrap cases - // where the C++ getitem returns an assignable reference. - _flags |= F_setitem; - if (_has_this && _parameters.size() > 2) { - if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { - // Its first parameter is an int parameter, presumably an index. - _flags |= F_setitem_int; - } - } - _args_type = InterfaceMaker::AT_varargs; - break; - - case T_constructor: - if (_ftype->_flags & CPPFunctionType::F_copy_constructor) { - // It's a copy constructor. - _flags |= F_copy_constructor; - - } else if (_ftype->_flags & CPPFunctionType::F_move_constructor) { - - } else if (!_has_this && _parameters.size() > 0 && - (_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0) { - // A non-explicit non-copy constructor might be eligible for coercion, - // as long as it does not require explicit keyword args. - if ((_flags & F_explicit_args) == 0 || - _args_type != InterfaceMaker::AT_keyword_args) { - - _flags |= F_coerce_constructor; - } - } - - // Constructors always take varargs, and possibly keyword args. - _args_type = InterfaceMaker::AT_varargs; - for (size_t i = first_param; i < _parameters.size(); ++i) { - if (_parameters[i]._has_name) { - _args_type = InterfaceMaker::AT_keyword_args; - break; - } - } - break; - - default: - break; - } - - return true; -} - -std::string make_safe_name(const std::string &name) { - return InterrogateBuilder::clean_identifier(name); - /* - static const char safe_chars2[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; - std::string result = name; - - size_t pos = result.find_first_not_of(safe_chars2); - while (pos != std::string::npos) { - result[pos] = '_'; - pos = result.find_first_not_of(safe_chars2); - } - - return result; - */ -} diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h deleted file mode 100644 index e662e40b75..0000000000 --- a/dtool/src/interrogate/functionRemap.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionRemap.h - * @author drose - * @date 2001-09-19 - */ - -#ifndef FUNCTIONREMAP_H -#define FUNCTIONREMAP_H - -#include "dtoolbase.h" - -#include "interrogate_interface.h" -#include "vector_string.h" - -#include - -class InterrogateBuilder; -class InterrogateType; -class InterrogateFunction; -class ParameterRemap; -class CPPType; -class CPPInstance; -class CPPStructType; -class CPPScope; -class CPPFunctionType; -class InterfaceMaker; - -/** - * This class describes how to remap a C++ function (and its list of - * parameters and return type) to a wrapped function, for a particular - * scripting language. - * - * The InterfaceMaker class will create one of these for each function, - * including one for each instance of an overloaded function. - */ -class FunctionRemap { -public: - FunctionRemap(const InterrogateType &itype, - const InterrogateFunction &ifunc, - CPPInstance *cppfunc, int num_default_parameters, - InterfaceMaker *interface_maker); - ~FunctionRemap(); - - std::string get_parameter_name(int n) const; - std::string call_function(std::ostream &out, int indent_level, - bool convert_result, const std::string &container) const; - std::string call_function(std::ostream &out, int indent_level, - bool convert_result, const std::string &container, - const vector_string &pexprs) const; - - void write_orig_prototype(std::ostream &out, int indent_level, bool local=false, - int num_default_args=0) const; - - FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index); - - std::string get_call_str(const std::string &container, const vector_string &pexprs) const; - void write_call_args(std::ostream &out, const vector_string &pexprs) const; - - int get_min_num_args() const; - int get_max_num_args() const; - - class Parameter { - public: - bool _has_name; - std::string _name; - ParameterRemap *_remap; - }; - - enum Type { - T_normal, - T_constructor, - T_destructor, - T_typecast_method, - T_assignment_method, - T_typecast, - T_getter, - T_setter, - T_item_assignment_operator, - }; - - enum Flags { - F_getitem = 0x0001, - F_getitem_int = 0x0002, - F_size = 0x0004, - F_setitem = 0x0008, - F_setitem_int = 0x0010, - F_delitem = 0x0020, - F_delitem_int = 0x0040, - F_make_copy = 0x0080, - F_copy_constructor = 0x0100, - F_explicit_self = 0x0200, - F_iter = 0x0400, - F_compare_to = 0x0800, - F_coerce_constructor = 0x1000, - F_divide_integer = 0x2000, - F_hash = 0x4000, - F_explicit_args = 0x8000, - F_explicit_cls =0x10000, - }; - - typedef std::vector Parameters; - - Parameters _parameters; - ParameterRemap *_return_type; - bool _void_return; - bool _ForcedVoidReturn; - bool _has_this; - bool _blocking; - bool _extension; - bool _const_method; - size_t _first_true_parameter; - int _num_default_parameters; - Type _type; - int _flags; - int _args_type; - std::string _expression; - std::string _function_signature; - std::string _hash; - std::string _unique_name; - std::string _reported_name; - std::string _wrapper_name; - FunctionWrapperIndex _wrapper_index; - - bool _return_value_needs_management; - FunctionIndex _return_value_destructor; - bool _manage_reference_count; - - CPPType *_cpptype; - CPPScope *_cppscope; - CPPInstance *_cppfunc; - CPPFunctionType *_ftype; - - bool _is_valid; - -private: - std::string get_parameter_expr(size_t n, const vector_string &pexprs) const; - bool setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_maker); -}; - -std::string make_safe_name(const std::string & name); - - -#endif diff --git a/dtool/src/interrogate/functionWriter.cxx b/dtool/src/interrogate/functionWriter.cxx deleted file mode 100644 index 58937d3f3d..0000000000 --- a/dtool/src/interrogate/functionWriter.cxx +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriter.cxx - * @author drose - * @date 2001-09-14 - */ - -#include "functionWriter.h" - -/** - * - */ -FunctionWriter:: -FunctionWriter() { -} - -/** - * - */ -FunctionWriter:: -~FunctionWriter() { -} - -/** - * - */ -const std::string &FunctionWriter:: -get_name() const { - return _name; -} - -/** - * - */ -int FunctionWriter:: -compare_to(const FunctionWriter &other) const { - // Lexicographical string comparison. - - std::string::const_iterator n1, n2; - n1 = _name.begin(); - n2 = other._name.begin(); - while (n1 != _name.end() && n2 != other._name.end()) { - if (*n1 != *n2) { - return *n1 - *n2; - } - ++n1; - ++n2; - } - if (n1 != _name.end()) { - return -1; - } - if (n2 != other._name.end()) { - return 1; - } - return 0; -} - -/** - * Outputs the prototype for the function. - */ -void FunctionWriter:: -write_prototype(std::ostream &) { -} - -/** - * Outputs the code for the function. - */ -void FunctionWriter:: -write_code(std::ostream &) { -} diff --git a/dtool/src/interrogate/functionWriter.h b/dtool/src/interrogate/functionWriter.h deleted file mode 100644 index da2930ae0e..0000000000 --- a/dtool/src/interrogate/functionWriter.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriter.h - * @author drose - * @date 2001-09-14 - */ - -#ifndef FUNCTIONWRITER_H -#define FUNCTIONWRITER_H - -#include "dtoolbase.h" - -/** - * This is an abstract class that can be used by the various InterfaceMakers - * to indicate a generic helper function or variable that needs to be written - * to the generated source file. - */ -class FunctionWriter { -public: - FunctionWriter(); - virtual ~FunctionWriter(); - - const std::string &get_name() const; - virtual int compare_to(const FunctionWriter &other) const; - - virtual void write_prototype(std::ostream &out); - virtual void write_code(std::ostream &out); - -protected: - std::string _name; -}; - -#endif diff --git a/dtool/src/interrogate/functionWriterPtrFromPython.cxx b/dtool/src/interrogate/functionWriterPtrFromPython.cxx deleted file mode 100644 index 016d79cff7..0000000000 --- a/dtool/src/interrogate/functionWriterPtrFromPython.cxx +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriterPtrFromPython.cxx - * @author drose - * @date 2001-09-14 - */ - -#include "functionWriterPtrFromPython.h" -#include "typeManager.h" -#include "interrogateBuilder.h" -#include "interrogate.h" - -#include "cppPointerType.h" - -/** - * - */ -FunctionWriterPtrFromPython:: -FunctionWriterPtrFromPython(CPPType *type) { - _type = TypeManager::unwrap_const(TypeManager::unwrap_pointer(type)); - _name = - "from_python_" + - InterrogateBuilder::clean_identifier(_type->get_local_name(&parser)); - - _pointer_type = new CPPPointerType(_type); -} - -/** - * - */ -FunctionWriterPtrFromPython:: -~FunctionWriterPtrFromPython() { - delete _pointer_type; -} - -/** - * Outputs the prototype for the function. - */ -void FunctionWriterPtrFromPython:: -write_prototype(std::ostream &out) { - CPPType *ppointer = new CPPPointerType(_pointer_type); - - out << "static int " << _name << "(PyObject *obj, "; - ppointer->output_instance(out, "addr", &parser); - out << ");\n"; - - delete ppointer; -} - -/** - * Outputs the code for the function. - */ -void FunctionWriterPtrFromPython:: -write_code(std::ostream &out) { - CPPType *ppointer = new CPPPointerType(_pointer_type); - - out << "static int\n" - << _name << "(PyObject *obj, "; - ppointer->output_instance(out, "addr", &parser); - out << ") {\n" - << " if (obj != nullptr && PyInstance_Check(obj)) {\n" - // << " PyClassObject *in_class = ((PyInstanceObject - // *)obj)->in_class;\n" - << " PyObject *in_dict = ((PyInstanceObject *)obj)->in_dict;\n" - << " if (in_dict != nullptr && PyDict_Check(in_dict)) {\n" - << " PyObject *thisobj = PyDict_GetItemString(in_dict, \"this\");\n" - << " if (thisobj != nullptr && PyLong_Check(thisobj)) {\n" - << " (*addr) = (" - << _pointer_type->get_local_name(&parser) << ")PyLong_AsVoidPtr(thisobj);\n" - << " return 1;\n" - << " }\n" - << " }\n" - << " }\n" - << " return 0;\n" - << "}\n\n"; - - delete ppointer; -} - -/** - * Returns the type that represents the actual data type. - */ -CPPType *FunctionWriterPtrFromPython:: -get_type() const { - return _type; -} - -/** - * Returns the type that represents a pointer to the data type. - */ -CPPType *FunctionWriterPtrFromPython:: -get_pointer_type() const { - return _pointer_type; -} diff --git a/dtool/src/interrogate/functionWriterPtrFromPython.h b/dtool/src/interrogate/functionWriterPtrFromPython.h deleted file mode 100644 index ca74f1dfdc..0000000000 --- a/dtool/src/interrogate/functionWriterPtrFromPython.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriterPtrFromPython.h - * @author drose - * @date 2001-09-14 - */ - -#ifndef FUNCTIONWRITERPTRFROMPYTHON_H -#define FUNCTIONWRITERPTRFROMPYTHON_H - -#include "functionWriter.h" - -class CPPType; - -/** - * This specialization of FunctionWriter generates a function that converts a - * PyObject pointer representing a class wrapper object to the corresponding - * C++ pointer. - */ -class FunctionWriterPtrFromPython : public FunctionWriter { -public: - FunctionWriterPtrFromPython(CPPType *type); - virtual ~FunctionWriterPtrFromPython(); - - virtual void write_prototype(std::ostream &out); - virtual void write_code(std::ostream &out); - CPPType *get_type() const; - CPPType *get_pointer_type() const; - -private: - CPPType *_type; - CPPType *_pointer_type; -}; - -#endif diff --git a/dtool/src/interrogate/functionWriterPtrToPython.cxx b/dtool/src/interrogate/functionWriterPtrToPython.cxx deleted file mode 100644 index e2486dae7c..0000000000 --- a/dtool/src/interrogate/functionWriterPtrToPython.cxx +++ /dev/null @@ -1,80 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriterPtrToPython.cxx - * @author drose - * @date 2001-09-14 - */ - -#include "functionWriterPtrToPython.h" -#include "typeManager.h" -#include "interrogateBuilder.h" -#include "interrogate.h" -#include "interfaceMakerPythonObj.h" - -#include "cppPointerType.h" - -/** - * - */ -FunctionWriterPtrToPython:: -FunctionWriterPtrToPython(CPPType *type) { - _type = TypeManager::unwrap_const(TypeManager::unwrap_pointer(type)); - _name = - "to_python_" + - InterrogateBuilder::clean_identifier(_type->get_local_name(&parser)); - - _pointer_type = new CPPPointerType(_type); -} - -/** - * - */ -FunctionWriterPtrToPython:: -~FunctionWriterPtrToPython() { - delete _pointer_type; -} - -/** - * Outputs the prototype for the function. - */ -void FunctionWriterPtrToPython:: -write_prototype(std::ostream &out) { - out << "static PyObject *" << _name << "("; - _pointer_type->output_instance(out, "addr", &parser); - out << ", int caller_manages);\n"; -} - -/** - * Outputs the code for the function. - */ -void FunctionWriterPtrToPython:: -write_code(std::ostream &out) { - std::string classobj_func = InterfaceMakerPythonObj::get_builder_name(_type); - out << "static PyObject *\n" - << _name << "("; - _pointer_type->output_instance(out, "addr", &parser); - out << ", int caller_manages) {\n" - << " PyObject *" << classobj_func << "();\n" - << " PyObject *classobj = " << classobj_func << "();\n" - << " PyInstanceObject *instance = (PyInstanceObject *)PyInstance_New(classobj, nullptr, nullptr);\n" - << " if (instance != nullptr) {\n" - << " PyObject *thisptr = PyLong_FromVoidPtr((void*)addr);\n" - << " PyDict_SetItemString(instance->in_dict, \"this\", thisptr);\n" - << " }\n" - << " return (PyObject *)instance;\n" - << "}\n\n"; -} - -/** - * Returns the type that represents a pointer to the data type. - */ -CPPType *FunctionWriterPtrToPython:: -get_pointer_type() const { - return _pointer_type; -} diff --git a/dtool/src/interrogate/functionWriterPtrToPython.h b/dtool/src/interrogate/functionWriterPtrToPython.h deleted file mode 100644 index f563d4fccb..0000000000 --- a/dtool/src/interrogate/functionWriterPtrToPython.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriterPtrToPython.h - * @author drose - * @date 2001-09-14 - */ - -#ifndef FUNCTIONWRITERPTRTOPYTHON_H -#define FUNCTIONWRITERPTRTOPYTHON_H - -#include "functionWriter.h" - -class CPPType; - -/** - * This specialization of FunctionWriter generates a function that generates a - * PyObject class wrapper object around the corresponding C++ pointer. - */ -class FunctionWriterPtrToPython : public FunctionWriter { -public: - FunctionWriterPtrToPython(CPPType *type); - virtual ~FunctionWriterPtrToPython(); - - virtual void write_prototype(std::ostream &out); - virtual void write_code(std::ostream &out); - CPPType *get_pointer_type() const; - -private: - CPPType *_type; - CPPType *_pointer_type; -}; - -#endif diff --git a/dtool/src/interrogate/functionWriters.cxx b/dtool/src/interrogate/functionWriters.cxx deleted file mode 100644 index 2d1d167b2d..0000000000 --- a/dtool/src/interrogate/functionWriters.cxx +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriters.cxx - * @author drose - * @date 2001-09-14 - */ - -#include "functionWriters.h" - -/** - * - */ -FunctionWriters:: -FunctionWriters() { -} - -/** - * - */ -FunctionWriters:: -~FunctionWriters() { - Writers::iterator wi; - for (wi = _writers.begin(); wi != _writers.end(); ++wi) { - delete (*wi); - } -} - -/** - * Adds the indicated FunctionWriter to the set of functions to be written, - * unless there is already a matching FunctionWriter. - * - * The return value is the FunctionWriter pointer that was added to the set, - * which may be the same pointer or a previously-allocated (but equivalent) - * pointer. - */ -FunctionWriter *FunctionWriters:: -add_writer(FunctionWriter *writer) { - std::pair result = _writers.insert(writer); - if (!result.second) { - // Already there; delete the pointer. - delete writer; - } - - // Return the pointer that is in the set. - return *result.first; -} - -/** - * Generates prototypes for all of the functions. - */ -void FunctionWriters:: -write_prototypes(std::ostream &out) { - Writers::iterator wi; - for (wi = _writers.begin(); wi != _writers.end(); ++wi) { - FunctionWriter *writer = (*wi); - writer->write_prototype(out); - } -} - -/** - * Generates all of the functions. - */ -void FunctionWriters:: -write_code(std::ostream &out) { - Writers::iterator wi; - for (wi = _writers.begin(); wi != _writers.end(); ++wi) { - FunctionWriter *writer = (*wi); - writer->write_code(out); - } -} diff --git a/dtool/src/interrogate/functionWriters.h b/dtool/src/interrogate/functionWriters.h deleted file mode 100644 index 2da07ecd9c..0000000000 --- a/dtool/src/interrogate/functionWriters.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file functionWriters.h - * @author drose - * @date 2001-09-14 - */ - -#ifndef FUNCTIONWRITERS_H -#define FUNCTIONWRITERS_H - -#include "dtoolbase.h" -#include "functionWriter.h" - -#include - -/** - * A set of zero or more FunctionWriter pointers accumulated by the various - * InterfaceMaker objects that are generating code for one particular output - * source file. - */ -class FunctionWriters { -public: - FunctionWriters(); - ~FunctionWriters(); - - FunctionWriter *add_writer(FunctionWriter *writer); - - void write_prototypes(std::ostream &out); - void write_code(std::ostream &out); - -protected: - class IndirectCompareTo { - public: - bool operator () (const FunctionWriter *a, const FunctionWriter *b) const { - return a->compare_to(*b) < 0; - } - }; - - typedef std::set Writers; - Writers _writers; -}; - -#endif diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx deleted file mode 100644 index 3c5d7f6b57..0000000000 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ /dev/null @@ -1,968 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMaker.cxx - * @author drose - * @date 2001-09-19 - */ - -#include "interfaceMaker.h" -#include "interrogateBuilder.h" -#include "typeManager.h" -#include "interrogate.h" -#include "functionRemap.h" -#include "parameterRemap.h" -#include "parameterRemapThis.h" -#include "parameterRemapUnchanged.h" -#include "parameterRemapReferenceToPointer.h" -#include "parameterRemapConcreteToPointer.h" -#include "parameterRemapEnumToInt.h" -#include "parameterRemapConstToNonConst.h" -#include "parameterRemapReferenceToConcrete.h" -#include "parameterRemapCharStarToString.h" -#include "parameterRemapBasicStringToString.h" -#include "parameterRemapBasicStringRefToString.h" -#include "parameterRemapBasicStringPtrToString.h" -#include "parameterRemapPTToPointer.h" - -#include "interrogateDatabase.h" -#include "interrogateManifest.h" -#include "interrogateElement.h" -#include "cppFunctionType.h" -#include "cppParameterList.h" -#include "cppMakeSeq.h" -#include "cppStructType.h" -#include "pnotify.h" - -using std::ostream; -using std::ostringstream; -using std::string; - -InterrogateType dummy_type; - -/** - * - */ -InterfaceMaker::Function:: -Function(const string &name, - const InterrogateType &itype, - const InterrogateFunction &ifunc) : - _name(name), - _itype(itype), - _ifunc(ifunc) -{ - _has_this = false; - _flags = 0; - _args_type = AT_unknown; -} - -/** - * - */ -InterfaceMaker::Function:: -~Function() { - Remaps::iterator ri; - for (ri = _remaps.begin(); ri != _remaps.end(); ++ri) { - delete (*ri); - } -} - -/** - * - */ -InterfaceMaker::MakeSeq:: -MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) : - _imake_seq(imake_seq), - _name(name), - _length_getter(nullptr), - _element_getter(nullptr) -{ -} - -/** - * - */ -InterfaceMaker::Property:: -Property(const InterrogateElement &ielement) : - _ielement(ielement), - _length_function(nullptr), - _has_function(nullptr), - _clear_function(nullptr), - _deleter(nullptr), - _inserter(nullptr), - _getkey_function(nullptr), - _has_this(false) -{ -} - -/** - * - */ -InterfaceMaker::Object:: -Object(const InterrogateType &itype) : - _itype(itype), - _protocol_types(0) -{ -} - -/** - * - */ -InterfaceMaker::Object:: -~Object() { -} - -/** - * To be called after all of the methods have been added, this checks which - * protocols this object appears to support (based on the methods it - * provides). - */ -void InterfaceMaker::Object:: -check_protocols() { - int flags = 0; - - Functions::const_iterator fi; - for (fi = _constructors.begin(); fi != _constructors.end(); ++fi) { - Function *func = (*fi); - flags |= func->_flags; - } - for (fi = _methods.begin(); fi != _methods.end(); ++fi) { - Function *func = (*fi); - flags |= func->_flags; - - if (func->_ifunc.get_name() == "__traverse__") { - // If we have a method named __traverse__, we implement Python's cyclic - // garbage collection protocol. - //XXX disabled for now because it's too unstable. - //_protocol_types |= PT_python_gc; - } - } - - if ((flags & (FunctionRemap::F_getitem_int | FunctionRemap::F_size)) == - (FunctionRemap::F_getitem_int | FunctionRemap::F_size)) { - // If we have both a getitem that receives an int, and a size, then we - // implement the sequence protocol: you can iterate through the elements - // of this object. - _protocol_types |= PT_sequence; - - } else if (flags & FunctionRemap::F_getitem) { - // If we have any getitem, then we implement the mapping protocol. - _protocol_types |= PT_mapping; - } - - if (flags & FunctionRemap::F_make_copy) { - // It's not exactly a protocol, but if we have a make_copy() method, we - // can use it to synthesize a __copy__ and __deepcopy__ Python method to - // support the copy module. - _protocol_types |= PT_make_copy; - } else if (flags & FunctionRemap::F_copy_constructor) { - // Ditto for the copy constructor. - _protocol_types |= PT_copy_constructor; - } - - if (flags & FunctionRemap::F_iter) { - _protocol_types |= PT_iter; - } -} - -/** - * Returns true if the first method found with the indicated name is a static - * method, false if it is an instance method. This does not test all - * overloads of the indicated name, merely the first one found. - */ -bool InterfaceMaker::Object:: -is_static_method(const string &name) { - Functions::const_iterator fi; - for (fi = _methods.begin(); fi != _methods.end(); ++fi) { - Function *func = (*fi); - if (!func->_remaps.empty()) { - FunctionRemap *remap = func->_remaps.front(); - string method_name = remap->_cppfunc->get_simple_name(); - if (method_name == name) { - return !func->_has_this; - } - } - } - - // Didn't find the requested function. - return false; -} - -/** - * - */ -InterfaceMaker:: -InterfaceMaker(InterrogateModuleDef *def) : - _def(def) -{ -} - -/** - * - */ -InterfaceMaker:: -~InterfaceMaker() { - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - delete object; - } - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - delete (*fi).second; - } -} - -/** - * Walks through the set of functions in the database and generates wrappers - * for each function, storing these in the database. No actual code should be - * output yet; this just updates the database with the wrapper information. - */ -void InterfaceMaker:: -generate_wrappers() { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - // We use a while loop rather than a simple for loop, because we might - // increase the number of types recursively during the traversal. - int ti = 0; - while (ti < idb->get_num_all_types()) { - TypeIndex type_index = idb->get_all_type(ti++); - record_object(type_index); - } - - int num_global_elements = idb->get_num_global_elements(); - for (int gi = 0; gi < num_global_elements; ++gi) { - //printf(" Global Type = %d", gi); - TypeIndex type_index = idb->get_global_element(gi); - record_object(type_index); - } - - int num_functions = idb->get_num_global_functions(); - for (int fi = 0; fi < num_functions; fi++) { - FunctionIndex func_index = idb->get_global_function(fi); - record_function(dummy_type, func_index); - } - - int num_manifests = idb->get_num_global_manifests(); - for (int mi = 0; mi < num_manifests; mi++) { - ManifestIndex manifest_index = idb->get_global_manifest(mi); - const InterrogateManifest &iman = idb->get_manifest(manifest_index); - if (iman.has_getter()) { - FunctionIndex func_index = iman.get_getter(); - record_function(dummy_type, func_index); - } - //printf(" Manifests %d\n", mi); - } - - int num_elements = idb->get_num_global_elements(); - for (int ei = 0; ei < num_elements; ei++) { - //printf(" Element %d\n", ei); - - ElementIndex element_index = idb->get_global_element(ei); - const InterrogateElement &ielement = idb->get_element(element_index); - if (ielement.has_getter()) { - FunctionIndex func_index = ielement.get_getter(); - record_function(dummy_type, func_index); - } - if (ielement.has_setter()) { - FunctionIndex func_index = ielement.get_setter(); - record_function(dummy_type, func_index); - } - } -} - -/** - * Generates the list of #include ... whatever that's required by this - * particular interface to the indicated output stream. - */ -void InterfaceMaker:: -write_includes(ostream &) { -} - -/** - * Generates the list of function prototypes corresponding to the functions - * that will be output in write_functions(). - */ -void InterfaceMaker:: -write_prototypes(ostream &out,ostream *out_h) { - _function_writers.write_prototypes(out); -} - -/** - * Generates the list of functions that are appropriate for this interface. - */ -void InterfaceMaker:: -write_functions(ostream &out) { - _function_writers.write_code(out); -} - -/** - * Generates whatever additional code is required to support a module file. - */ -void InterfaceMaker:: -write_module(ostream &, ostream *out_h, InterrogateModuleDef *) { -} - -/** - * Allocates a new ParameterRemap object suitable to the indicated parameter - * type. If struct_type is non-NULL, it is the type of the enclosing class - * for the function (method) in question. - * - * The return value is a newly-allocated ParameterRemap object, if the - * parameter type is acceptable, or NULL if the parameter type cannot be - * handled. - */ -ParameterRemap *InterfaceMaker:: -remap_parameter(CPPType *struct_type, CPPType *param_type) { - nassertr(param_type != nullptr, nullptr); - - if (convert_strings) { - if (TypeManager::is_char_pointer(param_type)) { - return new ParameterRemapCharStarToString(param_type); - } - if (TypeManager::is_wchar_pointer(param_type)) { - return new ParameterRemapWCharStarToWString(param_type); - } - - // If we're exporting a method of basic_string itself, don't convert - // basic_string's to atomic strings. - - if (struct_type == nullptr || - !(TypeManager::is_basic_string_char(struct_type) || - TypeManager::is_basic_string_wchar(struct_type))) { - if (TypeManager::is_basic_string_char(param_type)) { - return new ParameterRemapBasicStringToString(param_type); - - } else if (TypeManager::is_const_ref_to_basic_string_char(param_type)) { - return new ParameterRemapBasicStringRefToString(param_type); - - } else if (TypeManager::is_const_ptr_to_basic_string_char(param_type)) { - return new ParameterRemapBasicStringPtrToString(param_type); - - } else if (TypeManager::is_basic_string_wchar(param_type)) { - return new ParameterRemapBasicWStringToWString(param_type); - - } else if (TypeManager::is_const_ref_to_basic_string_wchar(param_type)) { - return new ParameterRemapBasicWStringRefToWString(param_type); - - } else if (TypeManager::is_const_ptr_to_basic_string_char(param_type)) { - return new ParameterRemapBasicStringPtrToString(param_type); - - } else if (TypeManager::is_const_ptr_to_basic_string_wchar(param_type)) { - return new ParameterRemapBasicWStringPtrToWString(param_type); - - } else if (TypeManager::is_reference(param_type) || - TypeManager::is_pointer(param_type)) { - // Python strings are immutable, so we can't wrap a non-const pointer - // or reference to a string. - CPPType *pt_type = TypeManager::unwrap(param_type); - if (TypeManager::is_basic_string_char(pt_type) || - TypeManager::is_basic_string_wchar(pt_type)) { - return nullptr; - } - } - } - if (struct_type == nullptr || - !TypeManager::is_vector_unsigned_char(struct_type)) { - if (TypeManager::is_vector_unsigned_char(param_type)) { - if (TypeManager::is_reference(param_type)) { - return new ParameterRemapReferenceToConcrete(param_type); - } else if (TypeManager::is_const(param_type)) { - return new ParameterRemapConstToNonConst(param_type); - } else { - return new ParameterRemapUnchanged(param_type); - } - } - } - } - - if (manage_reference_counts) { - if (TypeManager::is_pointer_to_base(param_type) || - TypeManager::is_const_ref_to_pointer_to_base(param_type)) - { - CPPType *pt_type = TypeManager::unwrap_reference(param_type); - - // Don't convert PointerTo<>'s to pointers for methods of the PointerTo - // itself! - if (struct_type == nullptr || - !(pt_type->get_local_name(&parser) == struct_type->get_local_name(&parser))) { - return new ParameterRemapPTToPointer(param_type); - } - } - } - - if (TypeManager::is_reference(param_type)) { - return new ParameterRemapReferenceToPointer(param_type); - - } else if (TypeManager::is_struct(param_type)) { - return new ParameterRemapConcreteToPointer(param_type); - - /* - } else if (TypeManager::is_enum(param_type) || TypeManager::is_const_ref_to_enum(param_type)) { - return new ParameterRemapEnumToInt(param_type); - */ - - // } else if (TypeManager::is_const_simple(param_type)) { return new - // ParameterRemapConstToNonConst(param_type); - - } else if (TypeManager::is_const_ref_to_simple(param_type)) { - return new ParameterRemapReferenceToConcrete(param_type); - - } else if (TypeManager::is_pointer(param_type) || - TypeManager::is_void(param_type) || - TypeManager::is_simple(param_type) || - TypeManager::is_simple_array(param_type)) { - return new ParameterRemapUnchanged(param_type); - - } else { - // Here's something we have a problem with. - return nullptr; - } -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require the implicit "this" parameter, if present, to be - * passed as the first parameter to any wrapper functions. - */ -bool InterfaceMaker:: -synthesize_this_parameter() { - return false; -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require overloaded instances of a function to be defined as - * separate functions (each with its own hashed name), or false for interfaces - * that can support overloading natively, and thus only require one wrapper - * function per each overloaded input function. - */ -bool InterfaceMaker:: -separate_overloading() { - return true; -} - -/** - * This method should be overridden and redefined to return false for - * interfaces that don't support global functions and should therefore will - * only accept function remaps that have a class associated. - */ -bool InterfaceMaker:: -wrap_global_functions() { - return true; -} - -/** - * Fills up the indicated vector with all of the FunctionRemap pointers - * created by this InterfaceMaker. It is the user's responsibility to empty - * the vector before calling this function; the new pointers will simply be - * added to the end. - */ -void InterfaceMaker:: -get_function_remaps(std::vector &remaps) { - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - Function::Remaps::const_iterator ri; - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - remaps.push_back(remap); - } - } -} - -/** - * - */ -ostream &InterfaceMaker:: -indent(ostream &out, int indent_level) { - for (int i = 0; i < indent_level; i++) { - out << ' '; - } - return out; -} - -/** - * Creates a FunctionRemap object corresponding to the particular function - * wrapper. - */ -FunctionRemap *InterfaceMaker:: -make_function_remap(const InterrogateType &itype, - const InterrogateFunction &ifunc, - CPPInstance *cppfunc, int num_default_parameters) { - FunctionRemap *remap = - new FunctionRemap(itype, ifunc, cppfunc, num_default_parameters, this); - if (remap->_is_valid) { - if (separate_overloading()) { - hash_function_signature(remap); - remap->_unique_name = - get_unique_prefix() + _def->library_hash_name + remap->_hash; - remap->_wrapper_name = - get_wrapper_prefix() + _def->library_hash_name + remap->_hash; - remap->_reported_name = remap->_wrapper_name; - - if (true_wrapper_names) { - remap->_reported_name = - InterrogateBuilder::clean_identifier(remap->_cppfunc->get_local_name(&parser)); - } - } - return remap; - } - - // No such FunctionRemap is valid. Return NULL. - delete remap; - return nullptr; -} - -/** - * Returns the function name that will be used to wrap the indicated function. - * - * This is the name for the overall wrapper function, including all of the - * overloaded instances. Interfaces that must define a different wrapper for - * each FunctionRemap object (i.e. for each instance of an overloaded - * function) need not define a name here. - */ -string InterfaceMaker:: -get_wrapper_name(const InterrogateType &itype, - const InterrogateFunction &ifunc, - FunctionIndex func_index) { - string func_name = ifunc.get_scoped_name(); - string clean_name = InterrogateBuilder::clean_identifier(func_name); - - ostringstream new_name; - new_name << get_wrapper_prefix() << clean_name << "_" << func_index; - return new_name.str(); -} - -/** - * Returns the prefix string used to generate wrapper function names. - */ -string InterfaceMaker:: -get_wrapper_prefix() { - return "xx_"; -} - -/** - * Returns the prefix string used to generate unique symbolic names, which are - * not necessarily C-callable function names. - */ -string InterfaceMaker:: -get_unique_prefix() { - return "x"; -} - -/** - * Records the indicated function, along with all of its FunctionRemap flavors - * and FunctionWriter helpers, for future output. Returns the new Function - * pointer. - */ -InterfaceMaker::Function *InterfaceMaker:: -record_function(const InterrogateType &itype, FunctionIndex func_index) { - assert(func_index != 0); - - if (_functions.count(func_index)) { - // Already exists. - return _functions[func_index]; - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateFunction &ifunc = idb->get_function(func_index); - - string wrapper_name = get_wrapper_name(itype, ifunc, func_index); - Function *func = new Function(wrapper_name, itype, ifunc); - _functions[func_index] = func; - -// printf(" Function Name = %s\n", ifunc.get_name().c_str()); - - // Now get all the valid FunctionRemaps for the function. - if (ifunc._instances != nullptr) { - InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); ii != ifunc._instances->end(); ++ii) { - CPPInstance *cppfunc = (*ii).second; - CPPFunctionType *ftype = cppfunc->_type->as_function_type(); - int max_default_parameters = 0; - - if (separate_overloading()) { - // Count up the number of default parameters this function might take. - CPPParameterList *parameters = ftype->_parameters; - CPPParameterList::Parameters::reverse_iterator pi; - for (pi = parameters->_parameters.rbegin(); - pi != parameters->_parameters.rend(); - ++pi) { - CPPInstance *param = (*pi); - if (param->_initializer != nullptr) { - // This parameter has a default value. - max_default_parameters++; - } else { - // The first parameter without a default value ends the search. - break; - } - } - } - - // Now make a different wrapper for each combination of default - // parameters. This will happen only if separate_overloading(), tested - // above, returned true; otherwise, max_default_parameters will be 0 and - // the loop will only be traversed once. - for (int num_default_parameters = 0; - num_default_parameters <= max_default_parameters; - num_default_parameters++) { - FunctionRemap *remap = - make_function_remap(itype, ifunc, cppfunc, num_default_parameters); - if (remap != nullptr) { - - func->_remaps.push_back(remap); - - // If *any* of the variants of this function has a "this" pointer, - // the entire set of functions is deemed to have a "this" pointer. - if (remap->_has_this || (remap->_flags & FunctionRemap::F_explicit_self) != 0) { - func->_has_this = true; - } - - func->_flags |= remap->_flags; - func->_args_type = (ArgsType)((int)func->_args_type | (int)remap->_args_type); - - // Make a wrapper for the function. - FunctionWrapperIndex wrapper_index = - remap->make_wrapper_entry(func_index); - if (wrapper_index != 0) { - InterrogateFunction &mod_ifunc = idb->update_function(func_index); - record_function_wrapper(mod_ifunc, wrapper_index); - } - } - } - } - } - - return func; -} - -/** - * Associates the function wrapper with its function in the appropriate - * structures in the database. - */ -void InterfaceMaker:: -record_function_wrapper(InterrogateFunction &, FunctionWrapperIndex) { -} - -/** - * Records the indicated type, which may be a struct type, along with all of - * its associated methods, if any. - */ -InterfaceMaker::Object *InterfaceMaker:: -record_object(TypeIndex type_index) { - if (type_index == 0) { - // An invalid type. - return nullptr; - } - - Objects::iterator oi = _objects.find(type_index); - if (oi != _objects.end()) { - // The object has previously been recorded. - return (*oi).second; - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); - - Object *object = new Object(itype); - bool inserted = _objects.insert(Objects::value_type(type_index, object)).second; - assert(inserted); - - Function *function; - - int num_constructors = itype.number_of_constructors(); - for (int ci = 0; ci < num_constructors; ci++) { - function = record_function(itype, itype.get_constructor(ci)); - object->_constructors.push_back(function); - } - - int num_methods = itype.number_of_methods(); - int mi; - for (mi = 0; mi < num_methods; mi++) { - function = record_function(itype, itype.get_method(mi)); - object->_methods.push_back(function); - } - - int num_casts = itype.number_of_casts(); - for (mi = 0; mi < num_casts; mi++) { - function = record_function(itype, itype.get_cast(mi)); - object->_methods.push_back(function); - } - - int num_derivations = itype.number_of_derivations(); - for (int di = 0; di < num_derivations; di++) { - if (itype.derivation_has_upcast(di)) { - record_function(itype, itype.derivation_get_upcast(di)); - } - if (itype.derivation_has_downcast(di)) { - // Downcasts are methods of the base class, not the child class. - TypeIndex base_type_index = itype.get_derivation(di); - const InterrogateType &base_type = idb->get_type(base_type_index); - record_function(base_type, itype.derivation_get_downcast(di)); - } - } - - int num_elements = itype.number_of_elements(); - for (int ei = 0; ei < num_elements; ei++) { - ElementIndex element_index = itype.get_element(ei); - const InterrogateElement &ielement = idb->get_element(element_index); - if (ielement.has_getter()) { - FunctionIndex func_index = ielement.get_getter(); - record_function(itype, func_index); - } - if (ielement.has_setter()) { - FunctionIndex func_index = ielement.get_setter(); - record_function(itype, func_index); - } - } - - object->check_protocols(); - - int num_nested = itype.number_of_nested_types(); - for (int ni = 0; ni < num_nested; ni++) { - TypeIndex nested_index = itype.get_nested_type(ni); - record_object(nested_index); - } - - return object; -} - -/** - * Does any additional processing that we might want to do on the return value - * for the function, just before we return it. Returns the string - * representing the new return value after processing. - */ -string InterfaceMaker:: -manage_return_value(ostream &out, int indent_level, - FunctionRemap *remap, const string &return_expr) const { - if (remap->_manage_reference_count) { - // If we're managing reference counts, and we're about to return a - // reference countable object, then increment its count. - if (return_expr == "return_value") { - // If the expression is just a variable name, we can just ref it - // directly. - output_ref(out, indent_level, remap, return_expr); - return return_expr; - - } else { - // Otherwise, we should probably assign it to a temporary first, so we - // don't invoke the function twice or something. - CPPType *type = remap->_return_type->get_temporary_type(); - indent(out, indent_level); - type->output_instance(out, "refcount", &parser); - out << " = " << return_expr << ";\n"; - - indent(out, indent_level) - << "if (" << return_expr << " != nullptr) {\n"; - indent(out, indent_level + 2) - << "(" << return_expr << ")->ref();\n"; - indent(out, indent_level) - << "}\n"; - output_ref(out, indent_level, remap, "refcount"); - return remap->_return_type->temporary_to_return("refcount"); - } - } - - // Otherwise, just return the expression unchanged. - return return_expr; -} - -/** - * Cleans up the given return value by deleting it or decrementing its - * reference count or whatever is appropriate. - */ -void InterfaceMaker:: -delete_return_value(ostream &out, int indent_level, - FunctionRemap *remap, const string &return_expr) const { - if (remap->_manage_reference_count) { - // If we're managing reference counts, and we're about to return a - // reference countable object, then decrement its count. - output_unref(out, indent_level, remap, return_expr); - - } else if (remap->_return_value_needs_management) { - // We should just delete it directly. - indent(out, indent_level) << "delete " << return_expr << ";\n"; - } -} - -/** - * Outputs the code to increment the reference count for the indicated - * variable name. - */ -void InterfaceMaker:: -output_ref(ostream &out, int indent_level, FunctionRemap *remap, - const string &varname) const { - - if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) { - // Actually, we have it stored in a PointerTo. No need to do anything. - return; - } - - if (remap->_type == FunctionRemap::T_constructor || - remap->_type == FunctionRemap::T_typecast) { - // In either of these cases, we can safely assume the pointer will never - // be NULL. - indent(out, indent_level) - << varname << "->ref();\n"; - - } else { - // However, in the general case, we have to check for that before we - // attempt to ref it. - - indent(out, indent_level) - << "if (" << varname << " != nullptr) {\n"; - indent(out, indent_level + 2) - << varname << "->ref();\n"; - indent(out, indent_level) - << "}\n"; - } -} - -/** - * Outputs the code to decrement the reference count for the indicated - * variable name. - */ -void InterfaceMaker:: -output_unref(ostream &out, int indent_level, FunctionRemap *remap, - const string &varname) const { - - if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) { - // Actually, we have it stored in a PointerTo. No need to do anything. - return; - } - - if (remap->_type == FunctionRemap::T_constructor || - remap->_type == FunctionRemap::T_typecast) { - // In either of these cases, we can safely assume the pointer will never - // be NULL. - indent(out, indent_level) - << "unref_delete(" << varname << ");\n"; - - } else { - // However, in the general case, we have to check for that before we - // attempt to ref it. - - indent(out, indent_level) - << "if (" << varname << " != nullptr) {\n"; - - if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) { - // We're sure the reference count won't reach zero since we have it - // stored in a PointerTo, so call the unref() method directly. - indent(out, indent_level + 2) - << varname << "->unref();\n"; - } else { - indent(out, indent_level + 2) - << "unref_delete(" << varname << ");\n"; - } - - indent(out, indent_level) - << "}\n"; - } -} - -/** - * Generates a unique string that corresponds to the function signature for - * the indicated FunctionRemap object, and stores the generated string in the - * _hash member of the FunctionRemap. - */ -void InterfaceMaker:: -hash_function_signature(FunctionRemap *remap) { - string hash = InterrogateBuilder::hash_string(remap->_function_signature, 5); - - // Now make sure we don't have another function with the same hash. - WrappersByHash::iterator hi; - hi = _wrappers_by_hash.find(hash); - if (hi == _wrappers_by_hash.end()) { - // No other name; we're in the clear. - _wrappers_by_hash[hash] = remap; - remap->_hash = hash; - return; - } - - if ((*hi).second != nullptr && - (*hi).second->_function_signature == remap->_function_signature) { - // The same function signature has already appeared. This shouldn't - // happen. - nout << "Internal error! Function signature " - << remap->_function_signature << " repeated!\n"; - remap->_hash = hash; - abort(); - return; - } - - // We have a conflict. Extend both strings to resolve the ambiguity. - if ((*hi).second != nullptr) { - FunctionRemap *other_remap = (*hi).second; - (*hi).second = nullptr; - other_remap->_hash += - InterrogateBuilder::hash_string(other_remap->_function_signature, 11); - bool inserted = _wrappers_by_hash.insert - (WrappersByHash::value_type(other_remap->_hash, other_remap)).second; - if (!inserted) { - nout << "Internal error! Hash " << other_remap->_hash - << " already appears!\n"; - } - } - - hash += InterrogateBuilder::hash_string(remap->_function_signature, 11); - bool inserted = _wrappers_by_hash.insert - (WrappersByHash::value_type(hash, remap)).second; - - if (!inserted) { - // Huh. We still have a conflict. This should be extremely rare. Well, - // just tack on a letter until it's resolved. - string old_hash = hash; - for (char ch = 'a'; ch <= 'z' && !inserted; ch++) { - hash = old_hash + ch; - inserted = _wrappers_by_hash.insert - (WrappersByHash::value_type(hash, remap)).second; - } - if (!inserted) { - nout << "Internal error! Too many conflicts with hash " - << hash << "\n"; - } - } - - remap->_hash = hash; -} - -/** - * Generates a string to output a spammy message to notify indicating we have - * just called this function. - */ -void InterfaceMaker:: -write_spam_message(ostream &out, FunctionRemap *remap) const { - ostringstream strm; - remap->write_orig_prototype(strm, 0); - string prototype = strm.str(); - - out << - " if (interrogatedb_cat.is_spam()) {\n" - " interrogatedb_cat.spam() << \""; - - for (string::const_iterator si = prototype.begin(); - si != prototype.end(); - ++si) { - switch (*si) { - case '"': - out << "\\\""; - break; - - case '\\': - out << "\\\\"; - break; - - default: - out << *si; - } - } - - out << "\\n\";\n" - " }\n"; -} diff --git a/dtool/src/interrogate/interfaceMaker.h b/dtool/src/interrogate/interfaceMaker.h deleted file mode 100644 index e439105ea1..0000000000 --- a/dtool/src/interrogate/interfaceMaker.h +++ /dev/null @@ -1,215 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMaker.h - * @author drose - * @date 2001-09-19 - */ - -#ifndef INTERFACEMAKER_H -#define INTERFACEMAKER_H - -#include "dtoolbase.h" - -#include "cppMakeSeq.h" - -#include "interrogate_interface.h" -#include "interrogate_request.h" -#include "functionWriters.h" - -#include -#include - -class FunctionRemap; -class ParameterRemap; -class CPPType; -class CPPInstance; -class InterrogateBuilder; -class InterrogateElement; -class InterrogateFunction; -class InterrogateMakeSeq; -class InterrogateType; - -/** - * This is an abstract base class that defines how to generate code that can - * be called from an external language (like Python or Squeak) and that can - * call into Panda. - * - * The specializations of this class like InterfaceMakerPython and - * InterfaceMakerC will generate the actual wrappers for the various language - * calling conventions. - */ -class InterfaceMaker { -public: - InterfaceMaker(InterrogateModuleDef *def); - virtual ~InterfaceMaker(); - - virtual void generate_wrappers(); - - virtual void write_includes(std::ostream &out); - virtual void write_prototypes(std::ostream &out, std::ostream *out_h); - virtual void write_functions(std::ostream &out); - virtual void write_module_support(std::ostream &out, std::ostream *out_h, InterrogateModuleDef *def) {}; - - virtual void write_module(std::ostream &out, std::ostream *out_h, InterrogateModuleDef *def); - - virtual ParameterRemap *remap_parameter(CPPType *struct_type, CPPType *param_type); - - virtual bool synthesize_this_parameter(); - virtual bool separate_overloading(); - virtual bool wrap_global_functions(); - - void get_function_remaps(std::vector &remaps); - - static std::ostream &indent(std::ostream &out, int indent_level); - -public: - // This contains information about the number of arguments that the wrapping - // function should take. - enum ArgsType { - // This is deliberately engineered such that these values can be OR'ed - // together to produce another valid enum value. - AT_unknown = 0x00, - - // The method or function takes no arguments. - AT_no_args = 0x01, - - // There is only a single argument. - AT_single_arg = 0x02, - - // The method takes a variable number of arguments. - AT_varargs = 0x03, - - // The method may take keyword arguments, if appropriate in the scripting - // language. Implies AT_varargs. - AT_keyword_args = 0x07, - }; - - class Function { - public: - Function(const std::string &name, - const InterrogateType &itype, - const InterrogateFunction &ifunc); - ~Function(); - - std::string _name; - const InterrogateType &_itype; - const InterrogateFunction &_ifunc; - typedef std::vector Remaps; - Remaps _remaps; - bool _has_this; - int _flags; - ArgsType _args_type; - }; - typedef std::map FunctionsByIndex; - typedef std::vector Functions; - FunctionsByIndex _functions; - - class MakeSeq { - public: - MakeSeq(const std::string &name, const InterrogateMakeSeq &imake_seq); - - const InterrogateMakeSeq &_imake_seq; - std::string _name; - Function *_length_getter; - Function *_element_getter; - }; - typedef std::vector MakeSeqs; - - class Property { - public: - Property(const InterrogateElement &ielement); - - const InterrogateElement &_ielement; - std::vector _getter_remaps; - std::vector _setter_remaps; - Function *_length_function; - Function *_has_function; - Function *_clear_function; - Function *_deleter; - Function *_inserter; - Function *_getkey_function; - bool _has_this; - }; - typedef std::vector Properties; - - class Object { - public: - Object(const InterrogateType &itype); - ~Object(); - - void check_protocols(); - bool is_static_method(const std::string &name); - - const InterrogateType &_itype; - Functions _constructors; - Functions _methods; - MakeSeqs _make_seqs; - Properties _properties; - - enum ProtocolTypes { - PT_sequence = 0x0001, - PT_mapping = 0x0002, - PT_make_copy = 0x0004, - PT_copy_constructor = 0x0008, - PT_iter = 0x0010, - PT_python_gc = 0x0020, - }; - int _protocol_types; - }; - typedef std::map Objects; - Objects _objects; - - typedef std::map WrappersByHash; - WrappersByHash _wrappers_by_hash; - - virtual FunctionRemap * - make_function_remap(const InterrogateType &itype, - const InterrogateFunction &ifunc, - CPPInstance *cppfunc, int num_default_parameters); - - virtual std::string - get_wrapper_name(const InterrogateType &itype, - const InterrogateFunction &ifunc, - FunctionIndex func_index); - virtual std::string get_wrapper_prefix(); - virtual std::string get_unique_prefix(); - - Function * - record_function(const InterrogateType &itype, FunctionIndex func_index); - - virtual void - record_function_wrapper(InterrogateFunction &ifunc, - FunctionWrapperIndex wrapper_index); - - virtual Object *record_object(TypeIndex type_index); - - void hash_function_signature(FunctionRemap *remap); - - - std::string - manage_return_value(std::ostream &out, int indent_level, - FunctionRemap *remap, const std::string &return_expr) const; - - void - delete_return_value(std::ostream &out, int indent_level, - FunctionRemap *remap, const std::string &return_expr) const; - - void output_ref(std::ostream &out, int indent_level, FunctionRemap *remap, - const std::string &varname) const; - void output_unref(std::ostream &out, int indent_level, FunctionRemap *remap, - const std::string &varname) const; - void write_spam_message(std::ostream &out, FunctionRemap *remap) const; - -protected: - InterrogateModuleDef *_def; - - FunctionWriters _function_writers; -}; - -#endif diff --git a/dtool/src/interrogate/interfaceMakerC.cxx b/dtool/src/interrogate/interfaceMakerC.cxx deleted file mode 100644 index 0deaa685be..0000000000 --- a/dtool/src/interrogate/interfaceMakerC.cxx +++ /dev/null @@ -1,253 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerC.cxx - * @author drose - * @date 2001-09-25 - */ - -#include "interfaceMakerC.h" -#include "interrogateBuilder.h" -#include "interrogate.h" -#include "functionRemap.h" -#include "parameterRemapHandleToInt.h" -#include "parameterRemapUnchanged.h" -#include "typeManager.h" - -#include "interrogateDatabase.h" -#include "interrogateType.h" -#include "interrogateFunction.h" -#include "cppFunctionType.h" - -using std::ostream; - -/** - * - */ -InterfaceMakerC:: -InterfaceMakerC(InterrogateModuleDef *def) : - InterfaceMaker(def) -{ -} - -/** - * - */ -InterfaceMakerC:: -~InterfaceMakerC() { -} - -/** - * Generates the list of function prototypes corresponding to the functions - * that will be output in write_functions(). - */ -void InterfaceMakerC:: -write_prototypes(ostream &out,ostream *out_h) { - // The 'used' attribute prevents emscripten from optimizing it out. - out << - "#if __GNUC__ >= 4\n" - "#define EXPORT_FUNC extern \"C\" __attribute__((used, visibility(\"default\")))\n" - "#else\n" - "#define EXPORT_FUNC extern \"C\"\n" - "#endif\n\n"; - - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - write_prototype_for(out, func); - } - - out << "\n"; - InterfaceMaker::write_prototypes(out,out_h); -} - -/** - * Generates the list of functions that are appropriate for this interface. - * This function is called *before* write_prototypes(), above. - */ -void InterfaceMakerC:: -write_functions(ostream &out) { - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - write_function_for(out, func); - } - - InterfaceMaker::write_functions(out); -} - -/** - * Allocates a new ParameterRemap object suitable to the indicated parameter - * type. If struct_type is non-NULL, it is the type of the enclosing class - * for the function (method) in question. - * - * The return value is a newly-allocated ParameterRemap object, if the - * parameter type is acceptable, or NULL if the parameter type cannot be - * handled. - */ -ParameterRemap *InterfaceMakerC:: -remap_parameter(CPPType *struct_type, CPPType *param_type) { - // Wrap TypeHandle and ButtonHandle, which are practically just ints, as an - // integer instead of a pointer. It makes things easier on the scripting - // language, especially if there has to be a dynamic downcasting system on - // the scripting language side. - if (TypeManager::is_handle(param_type)) { - return new ParameterRemapHandleToInt(param_type); - - } else { - return InterfaceMaker::remap_parameter(struct_type, param_type); - } -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require the implicit "this" parameter, if present, to be - * passed as the first parameter to any wrapper functions. - */ -bool InterfaceMakerC:: -synthesize_this_parameter() { - return true; -} - -/** - * Returns the prefix string used to generate wrapper function names. - */ -std::string InterfaceMakerC:: -get_wrapper_prefix() { - return "_inC"; -} - -/** - * Returns the prefix string used to generate unique symbolic names, which are - * not necessarily C-callable function names. - */ -std::string InterfaceMakerC:: -get_unique_prefix() { - return "c"; -} - -/** - * Associates the function wrapper with its function in the appropriate - * structures in the database. - */ -void InterfaceMakerC:: -record_function_wrapper(InterrogateFunction &ifunc, - FunctionWrapperIndex wrapper_index) { - ifunc._c_wrappers.push_back(wrapper_index); -} - -/** - * Writes the prototype for the indicated function. - */ -void InterfaceMakerC:: -write_prototype_for(ostream &out, InterfaceMaker::Function *func) { - Function::Remaps::const_iterator ri; - - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - - if (remap->_extension || (remap->_flags & FunctionRemap::F_explicit_self)) { - continue; - } - - if (output_function_names) { - out << "EXPORT_FUNC "; - } - write_function_header(out, func, remap, false); - out << ";\n"; - } -} - -/** - * Writes the definition for a function that will call the indicated C++ - * function or method. - */ -void InterfaceMakerC:: -write_function_for(ostream &out, InterfaceMaker::Function *func) { - Function::Remaps::const_iterator ri; - - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - write_function_instance(out, func, remap); - } -} - -/** - * Writes out the particular function that handles a single instance of an - * overloaded function. - */ -void InterfaceMakerC:: -write_function_instance(ostream &out, InterfaceMaker::Function *func, - FunctionRemap *remap) { - if (remap->_extension || (remap->_flags & FunctionRemap::F_explicit_self)) { - return; - } - - out << "/*\n" - << " * C wrapper for\n" - << " * "; - remap->write_orig_prototype(out, 0, false, remap->_num_default_parameters); - out << "\n" - << " */\n"; - - if (!output_function_names) { - // If we're not saving the function names, don't export it from the - // library. - out << "static "; - } - - write_function_header(out, func, remap, true); - out << " {\n"; - - if (generate_spam) { - write_spam_message(out, remap); - } - - std::string return_expr = - remap->call_function(out, 2, true, "param0"); - return_expr = manage_return_value(out, 2, remap, return_expr); - if (!return_expr.empty()) { - out << " return " << return_expr << ";\n"; - } - - out << "}\n\n"; -} - -/** - * Writes the first line of a function definition, either for a prototype or a - * function body. - */ -void InterfaceMakerC:: -write_function_header(ostream &out, InterfaceMaker::Function *func, - FunctionRemap *remap, bool newline) { - if (remap->_void_return) { - out << "void"; - } else { - out << remap->_return_type->get_new_type()->get_local_name(&parser); - } - if (newline) { - out << "\n"; - } else { - out << " "; - } - - out << remap->_wrapper_name << "("; - int pn = 0; - if (pn < (int)remap->_parameters.size()) { - remap->_parameters[pn]._remap->get_new_type()-> - output_instance(out, remap->get_parameter_name(pn), &parser); - pn++; - while (pn < (int)remap->_parameters.size()) { - out << ", "; - remap->_parameters[pn]._remap->get_new_type()-> - output_instance(out, remap->get_parameter_name(pn), &parser); - pn++; - } - } - out << ")"; -} diff --git a/dtool/src/interrogate/interfaceMakerC.h b/dtool/src/interrogate/interfaceMakerC.h deleted file mode 100644 index 91c8ef68bf..0000000000 --- a/dtool/src/interrogate/interfaceMakerC.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerC.h - * @author drose - * @date 2001-09-25 - */ - -#ifndef INTERFACEMAKERC_H -#define INTERFACEMAKERC_H - -#include "dtoolbase.h" - -#include "interfaceMaker.h" -#include "interrogate_interface.h" - -class FunctionRemap; - -/** - * An InteraceMaker suitable for generating a series of C-calling-convention - * functions for Panda class objects. - */ -class InterfaceMakerC : public InterfaceMaker { -public: - InterfaceMakerC(InterrogateModuleDef *def); - virtual ~InterfaceMakerC(); - - virtual void write_prototypes(std::ostream &out,std::ostream *out_h); - virtual void write_functions(std::ostream &out); - - virtual ParameterRemap *remap_parameter(CPPType *struct_type, CPPType *param_type); - - virtual bool synthesize_this_parameter(); - -protected: - virtual std::string get_wrapper_prefix(); - virtual std::string get_unique_prefix(); - - virtual void - record_function_wrapper(InterrogateFunction &ifunc, - FunctionWrapperIndex wrapper_index); - -private: - void write_prototype_for(std::ostream &out, Function *func); - void write_function_for(std::ostream &out, Function *func); - void write_function_instance(std::ostream &out, Function *func, - FunctionRemap *remap); - void write_function_header(std::ostream &out, Function *func, - FunctionRemap *remap, bool newline); -}; - -#endif diff --git a/dtool/src/interrogate/interfaceMakerPython.cxx b/dtool/src/interrogate/interfaceMakerPython.cxx deleted file mode 100644 index cfd82edf19..0000000000 --- a/dtool/src/interrogate/interfaceMakerPython.cxx +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPython.cxx - * @author drose - * @date 2001-09-21 - */ - -#include "interfaceMakerPython.h" -#include "interrogate.h" - -/** - * - */ -InterfaceMakerPython:: -InterfaceMakerPython(InterrogateModuleDef *def) : - InterfaceMaker(def) -{ -} - -/** - * Generates the list of #include ... whatever that's required by this - * particular interface to the indicated output stream. - */ -void InterfaceMakerPython:: -write_includes(std::ostream &out) { - InterfaceMaker::write_includes(out); - out << "#undef _POSIX_C_SOURCE\n" - << "#undef _XOPEN_SOURCE\n" - << "#define PY_SSIZE_T_CLEAN 1\n\n" - << "#if PYTHON_FRAMEWORK\n" - << " #include \n" - << "#else\n" - << " #include \"Python.h\"\n" - << "#endif\n"; -} - -/** - * Outputs code to check to see if an assertion has failed while the C++ code - * was executing, and report this failure back to Python. - */ -void InterfaceMakerPython:: -test_assert(std::ostream &out, int indent_level) const { - if (watch_asserts) { - out << "#ifndef NDEBUG\n"; - indent(out, indent_level) - << "Notify *notify = Notify::ptr();\n"; - indent(out, indent_level) - << "if (UNLIKELY(notify->has_assert_failed())) {\n"; - indent(out, indent_level + 2) - << "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n"; - indent(out, indent_level + 2) - << "notify->clear_assert_failed();\n"; - indent(out, indent_level + 2) - << "return nullptr;\n"; - indent(out, indent_level) - << "}\n"; - indent(out, indent_level) - << "if (PyErr_Occurred()) {\n"; - indent(out, indent_level + 2) - << "return nullptr;\n"; - indent(out, indent_level) - << "}\n"; - out << "#endif\n"; - } -} diff --git a/dtool/src/interrogate/interfaceMakerPython.h b/dtool/src/interrogate/interfaceMakerPython.h deleted file mode 100644 index 612e9ced17..0000000000 --- a/dtool/src/interrogate/interfaceMakerPython.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPython.h - * @author drose - * @date 2001-09-21 - */ - -#ifndef INTERFACEMAKERPYTHON_H -#define INTERFACEMAKERPYTHON_H - -#include "dtoolbase.h" - -#include "interfaceMaker.h" - -class FunctionRemap; - -/** - * The base class for InteraceMakerPythonSimple and InterfaceMakerPythonObj, - * this includes a few functions that both have in common for formatting - * Python objects. - */ -class InterfaceMakerPython : public InterfaceMaker { -protected: - InterfaceMakerPython(InterrogateModuleDef *def); - -public: - virtual void write_includes(std::ostream &out); - -protected: - virtual void test_assert(std::ostream &out, int indent_level) const; -}; - -#endif diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx deleted file mode 100644 index 162eaa4925..0000000000 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ /dev/null @@ -1,8739 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPythonNative.cxx - */ - -#include "interfaceMakerPythonNative.h" -#include "interrogateBuilder.h" -#include "interrogate.h" -#include "functionRemap.h" -#include "parameterRemapUnchanged.h" -#include "typeManager.h" - -#include "pnotify.h" // For nout -#include "interrogateDatabase.h" -#include "interrogateType.h" -#include "interrogateFunction.h" -#include "cppArrayType.h" -#include "cppConstType.h" -#include "cppEnumType.h" -#include "cppFunctionType.h" -#include "cppFunctionGroup.h" -#include "cppPointerType.h" -#include "cppTypeDeclaration.h" -#include "cppTypedefType.h" -#include "cppSimpleType.h" -#include "cppStructType.h" -#include "cppExpression.h" -#include "cppParameterList.h" -#include "cppReferenceType.h" -#include "lineStream.h" - -#include -#include -#include -#include - -using std::dec; -using std::hex; -using std::max; -using std::min; -using std::oct; -using std::ostream; -using std::ostringstream; -using std::set; -using std::string; - -extern InterrogateType dummy_type; -extern std::string EXPORT_IMPORT_PREFIX; - -#define CLASS_PREFIX "Dtool_" - -// Name Remapper... Snagged from ffi py code.... -struct RenameSet { - const char *_from; - const char *_to; - int function_type; -}; - -RenameSet methodRenameDictionary[] = { - { "operator ==" , "__eq__", 0 }, - { "operator !=" , "__ne__", 0 }, - { "operator << " , "__lshift__", 0 }, - { "operator >>" , "__rshift__", 0 }, - { "operator <" , "__lt__", 0 }, - { "operator >" , "__gt__", 0 }, - { "operator <=" , "__le__", 0 }, - { "operator >=" , "__ge__", 0 }, - { "operator <=>" , "__cmp__", 0 }, - { "operator =" , "assign", 0 }, - { "operator ()" , "__call__", 0 }, - { "operator []" , "__getitem__", 0 }, - { "operator []=" , "__setitem__", 0 }, - { "operator ++unary", "increment", 0 }, - { "operator ++" , "increment", 0 }, - { "operator --unary", "decrement", 0 }, - { "operator --" , "decrement", 0 }, - { "operator ^" , "__xor__", 0 }, - { "operator %" , "__mod__", 0 }, - { "operator !" , "logicalNot", 0 }, - { "operator ~unary", "__invert__", 0 }, - { "operator &" , "__and__", 0 }, - { "operator &&" , "logicalAnd", 0 }, - { "operator |" , "__or__", 0 }, - { "operator ||" , "logicalOr", 0 }, - { "operator +" , "__add__", 0 }, - { "operator -" , "__sub__", 0 }, - { "operator -unary", "__neg__", 0 }, - { "operator *" , "__mul__", 0 }, - { "operator /" , "__div__", 0 }, - { "operator +=" , "__iadd__", 1 }, - { "operator -=" , "__isub__", 1 }, - { "operator *=" , "__imul__", 1 }, - { "operator /=" , "__idiv__", 1 }, - { "operator ," , "concatenate", 0 }, - { "operator |=" , "__ior__", 1 }, - { "operator &=" , "__iand__", 1 }, - { "operator ^=" , "__ixor__", 1 }, - { "operator ~=" , "bitwiseNotEqual", 0 }, - { "operator ->" , "dereference", 0 }, - { "operator <<=" , "__ilshift__", 1 }, - { "operator >>=" , "__irshift__", 1 }, - { "operator typecast bool", "__bool__", 0 }, - { "__bool__" , "__bool__", 0 }, - { "__nonzero__" , "__nonzero__", 0 }, - { "__int__" , "__int__", 0 }, - { "__reduce__" , "__reduce__", 0 }, - { "__reduce_ex__" , "__reduce_ex__", 0 }, - { "__reduce_persist__", "__reduce_persist__", 0 }, - { "__copy__" , "__copy__", 0 }, - { "__deepcopy__" , "__deepcopy__", 0 }, - { "__getstate__" , "__getstate__", 0 }, - { "__setstate__" , "__setstate__", 0 }, - { "__new__" , "__new__", 0 }, - { "print" , "Cprint", 0 }, - { "CInterval.set_t", "_priv__cSetT", 0 }, - { nullptr, nullptr, -1 } -}; - -const char *pythonKeywords[] = { - "and", - "as", - "assert", - "async", - "await", - "break", - "class", - "continue", - "def", - "del", - "elif", - "else", - "except", - "exec", - "finally", - "for", - "from", - "global", - "if", - "import", - "in", - "is", - "lambda", - "nonlocal", - "not", - "or", - "pass", - "print", - "raise", - "return", - "try", - "while", - "with", - "yield", - nullptr -}; - -std::string -checkKeyword(std::string &cppName) { - for (int x = 0; pythonKeywords[x] != nullptr; x++) { - if (cppName == pythonKeywords[x]) { - return std::string("_") + cppName; - } - } - return cppName; -} - -std::string -classNameFromCppName(const std::string &cppName, bool mangle) { - if (!mangle_names) { - mangle = false; - } - - // # initialize to empty string - std::string className = ""; - - // # These are the characters we want to strip out of the name - const std::string badChars("!@#$%^&*()<>,.-=+~{}? "); - - bool nextCap = false; - bool nextUscore = false; - bool firstChar = true && mangle; - - for (std::string::const_iterator chr = cppName.begin(); - chr != cppName.end(); ++chr) { - if ((*chr == '_' || *chr == ' ') && mangle) { - nextCap = true; - - } else if (badChars.find(*chr) != std::string::npos) { - nextUscore = !mangle; - - } else if (nextCap || firstChar) { - className += toupper(*chr); - nextCap = false; - firstChar = false; - - } else if (nextUscore) { - className += '_'; - nextUscore = false; - className += *chr; - - } else { - className += *chr; - } - } - - if (className.empty()) { - std::string text = "** ERROR ** Renaming class: " + cppName + " to empty string"; - printf("%s", text.c_str()); - } - - className = checkKeyword(className); - // # FFIConstants.notify.debug('Renaming class: ' + cppName + ' to: ' + - // className) - return className; -} - -std::string -methodNameFromCppName(const std::string &cppName, const std::string &className, bool mangle) { - if (!mangle_names) { - mangle = false; - } - - std::string origName = cppName; - - if (origName.substr(0, 6) == "__py__") { - // By convention, a leading prefix of "__py__" is stripped. This - // indicates a Python-specific variant of a particular method. - origName = origName.substr(6); - } - - std::string methodName; - const std::string badChars("!@#$%^&*()<>,.-=+~{}? "); - bool nextCap = false; - for (std::string::const_iterator chr = origName.begin(); - chr != origName.end(); - chr++) { - if ((*chr == '_' || *chr == ' ') && mangle) { - nextCap = true; - - } else if (badChars.find(*chr) != std::string::npos) { - if (!mangle) { - methodName += '_'; - } - - } else if (nextCap) { - methodName += toupper(*chr); - nextCap = false; - - } else { - methodName += *chr; - } - } - - for (int x = 0; methodRenameDictionary[x]._from != nullptr; x++) { - if (origName == methodRenameDictionary[x]._from) { - methodName = methodRenameDictionary[x]._to; - } - } - - // # Mangle names that happen to be python keywords so they are not anymore - methodName = checkKeyword(methodName); - return methodName; -} - -std::string methodNameFromCppName(InterfaceMaker::Function *func, const std::string &className, bool mangle) { - std::string cppName = func->_ifunc.get_name(); - if (func->_ifunc.is_unary_op()) { - cppName += "unary"; - } - return methodNameFromCppName(cppName, className, mangle); -} - -std::string methodNameFromCppName(FunctionRemap *remap, const std::string &className, bool mangle) { - std::string cppName = remap->_cppfunc->get_local_name(); - if (remap->_ftype->_flags & CPPFunctionType::F_unary_op) { - cppName += "unary"; - } - return methodNameFromCppName(cppName, className, mangle); -} - -/** - * Determines whether this method should be mapped to one of Python's special - * slotted functions, those hard-coded functions that are assigned to - * particular function pointers within the object structure, for special - * functions like __getitem__ and __len__. - * - * Returns true if it has such a mapping, false if it is just a normal method. - * If it returns true, the SlottedFunctionDef structure is filled in with the - * important details. - */ -bool InterfaceMakerPythonNative:: -get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, - SlottedFunctionDef &def) { - if (obj == nullptr) { - // Only methods may be slotted. - return false; - } - - def._answer_location = string(); - def._wrapper_type = WT_none; - def._min_version = 0; - def._keep_method = false; - - string method_name = func->_ifunc.get_name(); - bool is_unary_op = func->_ifunc.is_unary_op(); - - if (method_name == "operator +" || - method_name == "__add__" || - method_name == "__radd__") { - def._answer_location = "nb_add"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator -" && is_unary_op) { - def._answer_location = "nb_negative"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "operator -" || - method_name == "__sub__" || - method_name == "__rsub__") { - def._answer_location = "nb_subtract"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator *" || - method_name == "__mul__" || - method_name == "__rmul__") { - def._answer_location = "nb_multiply"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator /") { - def._answer_location = "nb_divide"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "__truediv__" || - method_name == "__rtruediv__") { - def._answer_location = "nb_true_divide"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "__floordiv__" || - method_name == "__rfloordiv__") { - def._answer_location = "nb_floor_divide"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator %" || - method_name == "__mod__" || - method_name == "__rmod__") { - def._answer_location = "nb_remainder"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator <<" || - method_name == "__lshift__" || - method_name == "__rlshift__") { - def._answer_location = "nb_lshift"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator >>" || - method_name == "__rshift__" || - method_name == "__rrshift__") { - def._answer_location = "nb_rshift"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator ^" || - method_name == "__xor__" || - method_name == "__rxor__") { - def._answer_location = "nb_xor"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator ~" && is_unary_op) { - def._answer_location = "nb_invert"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "operator &" || - method_name == "__and__" || - method_name == "__rand__") { - def._answer_location = "nb_and"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator |" || - method_name == "__or__" || - method_name == "__ror__") { - def._answer_location = "nb_or"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "__pow__") { - def._answer_location = "nb_power"; - def._wrapper_type = WT_ternary_operator; - return true; - } - - if (method_name == "operator +=") { - def._answer_location = "nb_inplace_add"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator -=") { - def._answer_location = "nb_inplace_subtract"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator *=") { - def._answer_location = "nb_inplace_multiply"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator /=") { - def._answer_location = "nb_inplace_divide"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "__itruediv__") { - def._answer_location = "nb_inplace_true_divide"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "__ifloordiv__") { - def._answer_location = "nb_inplace_floor_divide"; - def._wrapper_type = WT_binary_operator; - return true; - } - - if (method_name == "operator %=") { - def._answer_location = "nb_inplace_remainder"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator <<=") { - def._answer_location = "nb_inplace_lshift"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator >>=") { - def._answer_location = "nb_inplace_rshift"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator &=") { - def._answer_location = "nb_inplace_and"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator ^=") { - def._answer_location = "nb_inplace_xor"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "operator |=") { - def._answer_location = "nb_inplace_or"; - def._wrapper_type = WT_inplace_binary_operator; - return true; - } - - if (method_name == "__ipow__") { - def._answer_location = "nb_inplace_power"; - def._wrapper_type = WT_inplace_ternary_operator; - return true; - } - - if (obj->_protocol_types & Object::PT_sequence) { - if (remap->_flags & FunctionRemap::F_getitem_int) { - def._answer_location = "sq_item"; - def._wrapper_type = WT_sequence_getitem; - return true; - } - if (remap->_flags & FunctionRemap::F_setitem_int || - remap->_flags & FunctionRemap::F_delitem_int) { - def._answer_location = "sq_ass_item"; - def._wrapper_type = WT_sequence_setitem; - return true; - } - if (remap->_flags & FunctionRemap::F_size) { - def._answer_location = "sq_length"; - def._wrapper_type = WT_sequence_size; - return true; - } - } - - if (obj->_protocol_types & Object::PT_mapping) { - if (remap->_flags & FunctionRemap::F_getitem) { - def._answer_location = "mp_subscript"; - def._wrapper_type = WT_one_param; - return true; - } - if (remap->_flags & FunctionRemap::F_setitem || - remap->_flags & FunctionRemap::F_delitem) { - def._answer_location = "mp_ass_subscript"; - def._wrapper_type = WT_mapping_setitem; - return true; - } - if (remap->_flags & FunctionRemap::F_size) { - def._answer_location = "mp_length"; - def._wrapper_type = WT_sequence_size; - return true; - } - } - - if (obj->_protocol_types & Object::PT_iter) { - if (method_name == "__iter__") { - def._answer_location = "tp_iter"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "next" || method_name == "__next__") { - def._answer_location = "tp_iternext"; - def._wrapper_type = WT_iter_next; - return true; - } - } - - if (method_name == "__await__") { - def._answer_location = "am_await"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "__aiter__") { - def._answer_location = "am_aiter"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "__anext__") { - def._answer_location = "am_anext"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "operator ()") { - def._answer_location = "tp_call"; - def._wrapper_type = WT_none; - return true; - } - - if (method_name == "__getattribute__") { - // Like __getattr__, but is called unconditionally, ie. does not try - // PyObject_GenericGetAttr first. - def._answer_location = "tp_getattro"; - def._wrapper_type = WT_one_param; - return true; - } - - if (method_name == "__getattr__") { - def._answer_location = "tp_getattro"; - def._wrapper_type = WT_getattr; - return true; - } - - if (method_name == "__setattr__") { - def._answer_location = "tp_setattro"; - def._wrapper_type = WT_setattr; - return true; - } - - if (method_name == "__delattr__") { - // __delattr__ shares the slot with __setattr__, except that it takes only - // one argument. - def._answer_location = "tp_setattro"; - def._wrapper_type = WT_setattr; - return true; - } - - if (method_name == "__nonzero__" || method_name == "__bool__") { - // Python 2 named it nb_nonzero, Python 3 nb_bool. We refer to it just as - // nb_bool. - def._answer_location = "nb_bool"; - def._wrapper_type = WT_inquiry; - return true; - } - - if (method_name == "__int__") { - def._answer_location = "nb_int"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "__getbuffer__") { - def._answer_location = "bf_getbuffer"; - def._wrapper_type = WT_getbuffer; - return true; - } - - if (method_name == "__releasebuffer__") { - def._answer_location = "bf_releasebuffer"; - def._wrapper_type = WT_releasebuffer; - return true; - } - - if (method_name == "__traverse__") { - def._answer_location = "tp_traverse"; - def._wrapper_type = WT_traverse; - return true; - } - - if (method_name == "__clear__") { - def._answer_location = "tp_clear"; - def._wrapper_type = WT_inquiry; - return true; - } - - if (method_name == "__repr__") { - def._answer_location = "tp_repr"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "__str__") { - def._answer_location = "tp_str"; - def._wrapper_type = WT_no_params; - return true; - } - - if (method_name == "__cmp__" || (remap->_flags & FunctionRemap::F_compare_to) != 0) { - def._answer_location = "tp_compare"; - def._wrapper_type = WT_compare; - def._keep_method = (method_name != "__cmp__"); - return true; - } - - if (method_name == "__hash__" || (remap->_flags & FunctionRemap::F_hash) != 0) { - def._answer_location = "tp_hash"; - def._wrapper_type = WT_hash; - def._keep_method = (method_name != "__hash__"); - return true; - } - - if (method_name == "__new__") { - def._answer_location = "tp_new"; - def._wrapper_type = WT_new; - return true; - } - - if (remap->_type == FunctionRemap::T_typecast_method) { - // A typecast operator. Check for a supported low-level typecast type. - if (TypeManager::is_bool(remap->_return_type->get_orig_type())) { - // If it's a bool type, then we wrap it with the __nonzero__ slot - // method. - def._answer_location = "nb_bool"; - def._wrapper_type = WT_inquiry; - return true; - - } else if (TypeManager::is_integer(remap->_return_type->get_orig_type())) { - // An integer type. - def._answer_location = "nb_int"; - def._wrapper_type = WT_no_params; - return true; - - } else if (TypeManager::is_float(remap->_return_type->get_orig_type())) { - // A floating-point (or double) type. - def._answer_location = "nb_float"; - def._wrapper_type = WT_no_params; - return true; - - } else if (remap->_return_type->new_type_is_atomic_string()) { - // A string type. - def._answer_location = "tp_str"; - def._wrapper_type = WT_no_params; - return true; - } - } - - return false; -} - -/** - * Determines whether the slot occurs in the map of slotted functions, and if - * so, writes out a pointer to its wrapper. If not, writes out def (usually - * 0). - */ -void InterfaceMakerPythonNative:: -write_function_slot(ostream &out, int indent_level, const SlottedFunctions &slots, - const string &slot, const string &default_) { - - SlottedFunctions::const_iterator rfi = slots.find(slot); - if (rfi == slots.end()) { - indent(out, indent_level) << default_ << ","; - if (default_ == "0") { - out << " // " << slot; - } - out << "\n"; - return; - } - - const SlottedFunctionDef &def = rfi->second; - - // Add an #ifdef if there is a specific version requirement on this - // function. - if (def._min_version > 0) { - out << "#if PY_VERSION_HEX >= 0x" << hex << def._min_version << dec << "\n"; - } - - indent(out, indent_level) << "&" << def._wrapper_name << ",\n"; - - if (def._min_version > 0) { - out << "#else\n"; - indent(out, indent_level) << default_ << ",\n"; - out << "#endif\n"; - } -} - -void InterfaceMakerPythonNative:: -get_valid_child_classes(std::map &answer, CPPStructType *inclass, const std::string &upcast_seed, bool can_downcast) { - if (inclass == nullptr) { - return; - } - - for (const CPPStructType::Base &base : inclass->_derivation) { -// if (base._vis <= V_public) can_downcast = false; - CPPStructType *base_type = TypeManager::resolve_type(base._base)->as_struct_type(); - if (base_type != nullptr) { - std::string scoped_name = base_type->get_local_name(&parser); - - if (answer.find(scoped_name) == answer.end()) { - answer[scoped_name]._can_downcast = can_downcast; - answer[scoped_name]._to_class_name = scoped_name; - answer[scoped_name]._structType = base_type; - - if (base._is_virtual) { - answer[scoped_name]._can_downcast = false; - } - - std::string local_upcast("("); - local_upcast += scoped_name + " *)"+ upcast_seed +""; - answer[scoped_name]._up_cast_string = local_upcast; - answer[scoped_name]._is_legal_py_class = is_cpp_type_legal(base_type); - } else { - answer[scoped_name]._can_downcast = false; - } - - get_valid_child_classes(answer, base_type, answer[scoped_name]._up_cast_string, answer[scoped_name]._can_downcast); - } - } -} - -/** - - */ -void InterfaceMakerPythonNative:: -write_python_instance(ostream &out, int indent_level, const string &return_expr, - bool owns_memory, const InterrogateType &itype, bool is_const) { - out << std::boolalpha; - - if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(TypeManager::resolve_type(itype._cpptype)); - } - - string class_name = itype.get_scoped_name(); - - // We don't handle final classes via DTool_CreatePyInstanceTyped since we - // know it can't be of a subclass type, so we don't need to do the downcast. - CPPStructType *struct_type = itype._cpptype->as_struct_type(); - if (IsPandaTypedObject(struct_type) && !struct_type->is_final()) { - // We can't let DTool_CreatePyInstanceTyped do the NULL check since we - // will be grabbing the type index (which would obviously crash when - // called on a NULL pointer), so we do it here. - indent(out, indent_level) - << "if (" << return_expr << " == nullptr) {\n"; - indent(out, indent_level) - << " return Py_NewRef(Py_None);\n"; - indent(out, indent_level) - << "} else {\n"; - // Special exception if we are returning TypedWritable, which might - // actually be a derived class that inherits from ReferenceCount. - if (!owns_memory && !is_const && class_name == "TypedWritable") { - indent(out, indent_level) - << " ReferenceCount *rc = " << return_expr << "->as_reference_count();\n"; - indent(out, indent_level) - << " bool is_refcount = (rc != nullptr);\n"; - indent(out, indent_level) - << " if (is_refcount) {\n"; - indent(out, indent_level) - << " rc->ref();\n"; - indent(out, indent_level) - << " }\n"; - indent(out, indent_level) - << " return DTool_CreatePyInstanceTyped((void *)" << return_expr - << ", *Dtool_Ptr_" << make_safe_name(class_name) << ", is_refcount, " - << is_const << ", " << return_expr - << "->get_type_index());\n"; - } else { - indent(out, indent_level) - << " return DTool_CreatePyInstanceTyped((void *)" << return_expr - << ", *Dtool_Ptr_" << make_safe_name(class_name) << ", " - << owns_memory << ", " << is_const << ", " - << return_expr << "->as_typed_object()->get_type_index());\n"; - } - indent(out, indent_level) - << "}\n"; - } else { - // DTool_CreatePyInstance will do the NULL check. - indent(out, indent_level) - << "return " - << "DTool_CreatePyInstance((void *)" << return_expr << ", " - << "*Dtool_Ptr_" << make_safe_name(class_name) << ", " - << owns_memory << ", " << is_const << ");\n"; - } -} - -/** - * - */ -InterfaceMakerPythonNative:: -InterfaceMakerPythonNative(InterrogateModuleDef *def) : - InterfaceMakerPython(def) -{ -} - -/** - * - */ -InterfaceMakerPythonNative:: -~InterfaceMakerPythonNative() { -} - -/** - * Generates the list of function prototypes corresponding to the functions - * that will be output in write_functions(). - */ -void InterfaceMakerPythonNative:: -write_prototypes(ostream &out_code, ostream *out_h) { - if (out_h != nullptr) { - *out_h << "#include \"py_panda.h\"\n\n"; - } - - /* - for (Function *func : _functions) { - if (!func->_itype.is_global() && is_function_legal(func)) { - write_prototype_for(out_code, func); - } - } - */ - - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - if (object->_itype.is_class() || object->_itype.is_struct()) { - if (is_cpp_type_legal(object->_itype._cpptype)) { - if (isExportThisRun(object->_itype._cpptype)) { - write_prototypes_class(out_code, out_h, object); - } else { - // write_prototypes_class_external(out_code, object); - // _external_imports.insert(object->_itype._cpptype); - } - } - } else if (object->_itype.is_scoped_enum() && isExportThisRun(object->_itype._cpptype)) { - // Forward declare where we will put the scoped enum type. - string class_name = object->_itype._cpptype->get_local_name(&parser); - string safe_name = make_safe_name(class_name); - out_code << "static PyTypeObject *Dtool_Ptr_" << safe_name << " = nullptr;\n"; - } - } - - out_code << "/**\n"; - out_code << " * Declarations for exported classes\n"; - out_code << " */\n"; - - out_code << "static const Dtool_TypeDef exports[] = {\n"; - - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - - if (object->_itype.is_class() || object->_itype.is_struct()) { - CPPType *type = object->_itype._cpptype; - - if (isExportThisRun(type) && is_cpp_type_legal(type)) { - string class_name = type->get_local_name(&parser); - string safe_name = make_safe_name(class_name); - - out_code << " {\"" << class_name << "\", &Dtool_" << safe_name << "},\n"; - } - } - } - - out_code << " {nullptr, nullptr},\n"; - out_code << "};\n\n"; - - out_code << "/**\n"; - out_code << " * Extern declarations for imported classes\n"; - out_code << " */\n"; - - // Write out a table of the externally imported types that will be filled in - // upon module initialization. - std::vector ext_imports(_external_imports.begin(), _external_imports.end()); - if (!ext_imports.empty()) { - out_code << "#ifndef LINK_ALL_STATIC\n"; - out_code << "static Dtool_TypeDef imports[] = {\n"; - - // Ensure that there is a deterministic ordering of external imports. - std::sort(ext_imports.begin(), ext_imports.end(), - [] (const CPPType *a, const CPPType *b) { - return a->get_local_name(&parser) < b->get_local_name(&parser); - }); - - int idx = 0; - for (CPPType *type : ext_imports) { - string class_name = type->get_local_name(&parser); - string safe_name = make_safe_name(class_name); - - out_code << " {\"" << class_name << "\", nullptr},\n"; - out_code << "#define Dtool_Ptr_" << safe_name << " (imports[" << idx << "].type)\n"; - ++idx; - } - out_code << " {nullptr, nullptr},\n"; - out_code << "};\n"; - out_code << "#endif\n\n"; - } - - for (CPPType *type : ext_imports) { - string class_name = type->get_local_name(&parser); - string safe_name = make_safe_name(class_name); - - out_code << "// " << class_name << "\n"; - - out_code << "#ifndef LINK_ALL_STATIC\n"; - // out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << - // safe_name << ";\n"; - //if (has_get_class_type_function(type)) { - // out_code << "static struct Dtool_PyTypedObject *Dtool_Ptr_" << safe_name << ";\n"; - //} - // out_code << "#define Dtool_Ptr_" << safe_name << " &Dtool_" << - // safe_name << "\n"; out_code << "IMPORT_THIS void - // Dtool_PyModuleClassInit_" << safe_name << "(PyObject *module);\n"; - - // This is some really ugly code, because we have to store a pointer with - // a function of a signature that differs from class to class. If someone - // can think of an elegant way to do this without sacrificing perf, let me - // know. - int has_coerce = has_coerce_constructor(type->as_struct_type()); - if (has_coerce > 0) { - if (TypeManager::is_reference_count(type)) { - out_code - << "inline static bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, CPT(" << class_name << ") &coerced) {\n" - << " nassertr(Dtool_Ptr_" << safe_name << " != nullptr, false);\n" - << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce != nullptr, false);\n" - << " return ((bool (*)(PyObject *, CPT(" << class_name << ") &))Dtool_Ptr_" << safe_name << "->_Dtool_ConstCoerce)(args, coerced);\n" - << "}\n"; - - if (has_coerce > 1) { - out_code - << "inline static bool Dtool_Coerce_" << safe_name << "(PyObject *args, PT(" << class_name << ") &coerced) {\n" - << " nassertr(Dtool_Ptr_" << safe_name << " != nullptr, false);\n" - << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != nullptr, false);\n" - << " return ((bool (*)(PyObject *, PT(" << class_name << ") &))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced);\n" - << "}\n"; - } - } else { - out_code - << "inline static " << class_name << " *Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " &coerced) {\n" - << " nassertr(Dtool_Ptr_" << safe_name << " != nullptr, nullptr);\n" - << " nassertr(Dtool_Ptr_" << safe_name << "->_Dtool_Coerce != nullptr, nullptr);\n" - << " return ((" << class_name << " *(*)(PyObject *, " << class_name << " &))Dtool_Ptr_" << safe_name << "->_Dtool_Coerce)(args, coerced);\n" - << "}\n"; - } - } - out_code << "#else\n"; - out_code << "extern struct Dtool_PyTypedObject Dtool_" << safe_name << ";\n"; - out_code << "static struct Dtool_PyTypedObject *const Dtool_Ptr_" << safe_name << " = &Dtool_" << safe_name << ";\n"; - - if (has_coerce > 0) { - if (TypeManager::is_reference_count(type)) { - out_code << "extern bool Dtool_ConstCoerce_" << safe_name << "(PyObject *args, CPT(" << class_name << ") &coerced);\n"; - if (has_coerce > 1) { - out_code << "extern bool Dtool_Coerce_" << safe_name << "(PyObject *args, PT(" << class_name << ") &coerced);\n"; - } - } else { - out_code << "extern " << class_name << " *Dtool_Coerce_" << safe_name << "(PyObject *args, " << class_name << " &coerced);\n"; - } - } - out_code << "#endif\n"; - } -} - -/** - * Output enough enformation to a declartion of a externally generated dtool - * type object - */ -void InterfaceMakerPythonNative:: -write_prototypes_class_external(ostream &out, Object *obj) { - std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); - std::string c_class_name = obj->_itype.get_true_name(); - std::string preferred_name = obj->_itype.get_name(); - - - out << "/**\n"; - out << " * Forward declaration of class " << class_name << "\n"; - out << " */\n"; - - // This typedef is necessary for class templates since we can't pass a comma - // to a macro function. - out << "typedef " << c_class_name << " " << class_name << "_localtype;\n"; - out << "Define_Module_Class_Forward(" << _def->module_name << ", " << class_name << ", " << class_name << "_localtype, " << classNameFromCppName(preferred_name, false) << ");\n"; -} - -/** - - */ -void InterfaceMakerPythonNative:: -write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) { - std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - - out_code << "/**\n"; - out_code << " * Forward declarations for top-level class " << ClassName << "\n"; - out_code << " */\n"; - - /* - for (Function *func : obj->_methods) { - write_prototype_for(out_code, func); - } - */ - - /* - for (Function *func : obj->_constructors) { - std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; - write_prototype_for_name(out_code, obj, func, fname); - } - */ - - write_class_declarations(out_code, out_h, obj); -} - -/** - * Generates the list of functions that are appropriate for this interface. - * This function is called *before* write_prototypes(), above. - */ -void InterfaceMakerPythonNative:: -write_functions(ostream &out) { - out << "/**\n"; - out << " * Python wrappers for global functions\n" ; - out << " */\n"; - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - if (!func->_itype.is_global() && is_function_legal(func)) { - write_function_for_top(out, nullptr, func); - } - } - - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - if (object->_itype.is_class() || object->_itype.is_struct()) { - if (is_cpp_type_legal(object->_itype._cpptype)) { - if (isExportThisRun(object->_itype._cpptype)) { - write_class_details(out, object); - } - } - } - } - - // Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - if (!object->_itype.get_outer_class()) { - if (object->_itype.is_class() || object->_itype.is_struct()) { - if (is_cpp_type_legal(object->_itype._cpptype)) { - if (isExportThisRun(object->_itype._cpptype)) { - write_module_class(out, object); - } - } - } - } - } -} - -/** - * Writes out all of the wrapper methods necessary to export the given object. - * This is called by write_functions. - */ -void InterfaceMakerPythonNative:: -write_class_details(ostream &out, Object *obj) { - // std::string cClassName = obj->_itype.get_scoped_name(); - std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - std::string cClassName = obj->_itype.get_true_name(); - - CPPType *cpptype = TypeManager::resolve_type(obj->_itype._cpptype); - CPPStructType *struct_type = cpptype->as_struct_type(); - - // Determine which external imports we will need. - std::map details; - std::map::iterator di; - builder.get_type(TypeManager::unwrap(cpptype), false); - get_valid_child_classes(details, cpptype->as_struct_type()); - for (di = details.begin(); di != details.end(); di++) { - // InterrogateType ptype =idb->get_type(di->first); - if (di->second._is_legal_py_class && !isExportThisRun(di->second._structType)) { - _external_imports.insert(TypeManager::resolve_type(di->second._structType)); - } - // out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << - // make_safe_name(di->second._to_class_name) << ";\n"; - } - - bool py_subclassable = is_python_subclassable(struct_type); - if (py_subclassable) { - assert(!obj->_constructors.empty()); - out << "/**\n"; - out << " * Proxy class for " << cClassName << "\n"; - out << " */\n"; - out << "class DtoolProxy_" << ClassName << " final : public " << cClassName << ", public DtoolProxy {\n"; - out << "public:\n"; - // I'd love just to use "using" to inherit the constructors from the base. - // However, MSVC seems to have a bug inheriting constructors with default - // arguments. - if (struct_type->is_default_constructible()) { - out << " DtoolProxy_" << ClassName << "() = default;\n"; - } - for (Function *func : obj->_constructors) { - for (FunctionRemap *remap : func->_remaps) { - CPPParameterList::Parameters ¶ms = remap->_ftype->_parameters->_parameters; - if (params.empty()) { - continue; - } - out << " DtoolProxy_" << ClassName << "("; - for (size_t i = 0; i < params.size(); ++i) { - if (i > 0) { - out << ", "; - } - params[i]->_type->output_instance(out, remap->get_parameter_name(i), &parser); - if (i > 0 && params[i]->_initializer != nullptr) { - out << " = " << *params[i]->_initializer; - } - } - out << ")"; - if (remap->_ftype->_flags & CPPFunctionType::F_noexcept) { - out << " noexcept"; - } - out << " : " << cClassName << "("; - for (size_t i = 0; i < params.size(); ++i) { - if (i > 0) { - out << ", "; - } - // Determine whether to pass with move semantics or not. - CPPType *param_type = params[i]->_type; - CPPType::SubType subtype = param_type->get_subtype(); - while (subtype == CPPDeclaration::ST_typedef) { - param_type = param_type->as_typedef_type()->_type; - subtype = param_type->get_subtype(); - } - if (subtype == CPPType::ST_pointer || - subtype == CPPType::ST_const || - subtype == CPPType::ST_enum || - subtype == CPPType::ST_simple || - (subtype == CPPType::ST_reference && param_type->as_reference_type()->_value_category == CPPReferenceType::VC_lvalue)) { - out << remap->get_parameter_name(i); - } else { - out << "std::move(" << remap->get_parameter_name(i) << ")"; - } - } - out << ") {}\n"; - } - } - - // Move constructor is never listed above, but we do use it. - if (struct_type->is_move_constructible()) { - out << " DtoolProxy_" << ClassName << "(" << cClassName << " &&from)"; - CPPInstance *ctor = struct_type->get_move_constructor(); - if (ctor != nullptr) { - CPPFunctionType *ftype = ctor->_type->as_function_type(); - if (ftype != nullptr && (ftype->_flags & CPPFunctionType::F_noexcept) != 0) { - out << " noexcept"; - } - } - out << " : " << cClassName << "(std::move(from)) {}\n"; - } - out << "\n"; - out << " virtual bool unref() const override {\n"; - out << " if (!(" << cClassName << "::unref())) {\n"; - out << " // It was cleaned up by the Python garbage collector.\n"; - out << " return false;\n"; - out << " }\n"; - out << " nassertr(DtoolProxy::_self != nullptr, true);\n"; - out << "\n"; - out << " // If the last reference to the object is the one being held by Python,\n"; - out << " // check whether the Python wrapper itself is also at a refcount of 1.\n"; - out << " bool result = true;\n"; - out << " if (get_ref_count() == 1) {\n"; - out << " PyGILState_STATE gstate = PyGILState_Ensure();\n"; - out << " int ref_count = Py_REFCNT(DtoolProxy::_self);\n"; - out << " assert(ref_count > 0);\n"; - out << " if (ref_count == 1) {\n"; - out << " // The last reference to the Python wrapper is being held by us.\n"; - out << " // Break the reference cycle and allow the object to go away.\n"; - out << " if (!" << cClassName << "::unref()) {\n"; - out << " PyObject_GC_UnTrack(DtoolProxy::_self);\n"; - out << " ((Dtool_PyInstDef *)DtoolProxy::_self)->_memory_rules = false;\n"; - out << " Py_CLEAR(DtoolProxy::_self);\n"; - out << "\n"; - out << " // Let the caller destroy the object.\n"; - out << " result = false;\n"; - out << " }\n"; - out << " }\n"; - //out << " else {\n"; - //out << " // There is still a Python reference. Make sure it can be cleaned up\n"; - //out << " // by the garbage collector when it gets to it.\n"; - //out << " if (!PyObject_GC_IsTracked(DtoolProxy::_self)) {\n"; - //out << " PyObject_GC_Track(DtoolProxy::_self);\n"; - //out << " }\n"; - //out << " }\n"; - out << " PyGILState_Release(gstate);\n"; - out << " }\n"; - out << " return result;\n"; - out << " }\n"; - out << "\n"; - out << " virtual TypeHandle get_type() const override {\n"; - out << " return DtoolProxy::_type;\n"; - out << " }\n"; - out << "\n"; - out << " virtual TypeHandle force_init_type() override {\n"; - out << " return DtoolProxy::_type;\n"; - out << " }\n"; - out << "};\n"; - out << "\n"; - - out << "static PyObject *Dtool_WrapProxy_" << ClassName << "(void *from_this, PyTypeObject *from_type) {\n"; - out << " DtoolProxy_" << ClassName << " *to_this;\n"; - out << " if (from_type == nullptr || from_type == &Dtool_" << ClassName << "._PyType) {\n"; - out << " to_this = (DtoolProxy_" << ClassName << " *)(" << cClassName << "*)from_this;\n"; - out << " }\n"; - for (di = details.begin(); di != details.end(); di++) { - if (di->second._can_downcast && di->second._is_legal_py_class) { - out << " else if (from_type == (PyTypeObject *)Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; - out << " " << di->second._to_class_name << " *other_this = (" << di->second._to_class_name << " *)from_this;\n" ; - out << " to_this = (DtoolProxy_" << ClassName << " *)(" << cClassName << " *)other_this;\n"; - out << " }\n"; - } - } - out << " else {\n"; - out << " return nullptr;\n"; - out << " }\n"; - out << " nassertr(to_this->DtoolProxy::_self != nullptr, nullptr);\n"; - out << " PyObject *result = Py_NewRef(to_this->DtoolProxy::_self);\n"; - // Directly call the parent class' unref(), because we know our version - // would only find that the Python refcount > 1 and do nothing else - out << " bool nonzero = to_this->" << cClassName << "::unref();\n"; - out << " nassertr(nonzero, result);\n"; - out << " return result;\n"; - out << "}\n\n"; - } - - out << "/**\n"; - out << " * Python wrappers for functions of class " << cClassName << "\n" ; - out << " */\n"; - - // First write out all the wrapper functions for the methods. - bool have_new = false; - for (Function *func : obj->_methods) { - if (func) { - // Write the definition of the generic wrapper function for this - // function. - if (func->_ifunc.get_name() == "__new__") { - have_new = true; - } - write_function_for_top(out, obj, func); - } - } - - // Now write out generated getters and setters for the properties. - for (Property *property : obj->_properties) { - write_getset(out, obj, property); - } - - // Write the constructors. - std::string fname = "static int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; - for (Function *func : obj->_constructors) { - string expected_params; - write_function_for_name(out, obj, func->_remaps, fname, expected_params, true, AT_keyword_args, RF_int); - } - if (obj->_constructors.size() == 0) { - // We still need to write a dummy constructor to prevent inheriting the - // constructor from a base class. - if (have_new) { - out << fname << " {\n" - " return 0;\n" - "}\n\n"; - } else { - out << fname << " {\n" - " Dtool_Raise_TypeError(\"cannot init abstract class\");\n" - " return -1;\n" - "}\n\n"; - } - } - - // If we have "coercion constructors", write a single wrapper to consolidate - // those. - int has_coerce = has_coerce_constructor(struct_type); - if (has_coerce > 0) { - write_coerce_constructor(out, obj, true); - if (has_coerce > 1 && TypeManager::is_reference_count(obj->_itype._cpptype)) { - write_coerce_constructor(out, obj, false); - } - } - - // Write make seqs: generated methods that return a sequence of items. - for (MakeSeq *make_seq : obj->_make_seqs) { - if (is_function_legal(make_seq->_length_getter) && - is_function_legal(make_seq->_element_getter)) { - write_make_seq(out, obj, ClassName, cClassName, make_seq); - } else { - if (!is_function_legal(make_seq->_length_getter)) { - nout << "illegal length function for MAKE_SEQ: " << make_seq->_length_getter->_name << "\n"; - } - if (!is_function_legal(make_seq->_element_getter)) { - nout << "illegal element function for MAKE_SEQ: " << make_seq->_element_getter->_name << "\n"; - } - } - } - - // Write support methods to cast from and to pointers of this type. - { - out << "static void *Dtool_UpcastInterface_" << ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type) {\n"; - out << " Dtool_PyTypedObject *type = DtoolInstance_TYPE(self);\n"; - out << " if (type != &Dtool_" << ClassName << ") {\n"; - out << " printf(\"%s ** Bad Source Type-- Requesting Conversion from %s to %s\\n\", \"" << ClassName << "\", Py_TYPE(self)->tp_name, requested_type->_PyType.tp_name); fflush(nullptr);\n"; - out << " return nullptr;\n"; - out << " }\n"; - out << "\n"; - out << " " << cClassName << " *local_this = (" << cClassName << " *)DtoolInstance_VOID_PTR(self);\n"; - out << " if (requested_type == &Dtool_" << ClassName << ") {\n"; - out << " return local_this;\n"; - out << " }\n"; - - for (di = details.begin(); di != details.end(); di++) { - if (di->second._is_legal_py_class) { - out << " if (requested_type == Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; - out << " return " << di->second._up_cast_string << " local_this;\n"; - out << " }\n"; - } - } - - // Are there any implicit cast operators that can cast this object to our - // desired pointer? - for (Function *func : obj->_methods) { - for (FunctionRemap *remap : func->_remaps) { - if (remap->_type == FunctionRemap::T_typecast_method && - is_remap_legal(remap) && - !remap->_return_type->return_value_needs_management() && - (remap->_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0 && - TypeManager::is_pointer(remap->_return_type->get_new_type())) { - - CPPType *cast_type = remap->_return_type->get_orig_type(); - CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(remap->_return_type->get_new_type())); - string return_expr = "(" + cast_type->get_local_name(&parser) + ")*local_this"; - out << " // " << *remap->_cppfunc << "\n"; - out << " if (requested_type == Dtool_Ptr_" << make_safe_name(obj_type->get_local_name(&parser)) << ") {\n"; - out << " return (void *)(" << remap->_return_type->get_return_expr(return_expr) << ");\n"; - out << " }\n"; - } - } - } - - out << " return nullptr;\n"; - out << "}\n\n"; - - //NB. This may be called with nullptr in either argument and should produce - // a valid wrapper object even with a null pointer. - out << "static PyObject *Dtool_Wrap_" << ClassName << "(void *from_this, PyTypeObject *from_type) {\n"; - out << " " << cClassName << " *to_this;\n"; - out << " if (from_type == nullptr || from_type == &Dtool_" << ClassName << "._PyType) {\n"; - out << " to_this = (" << cClassName << " *)from_this;\n"; - out << " }\n"; - for (di = details.begin(); di != details.end(); di++) { - if (di->second._can_downcast && di->second._is_legal_py_class) { - out << " else if (from_type == (PyTypeObject *)Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; - out << " " << di->second._to_class_name << " *other_this = (" << di->second._to_class_name << " *)from_this;\n" ; - out << " to_this = (" << cClassName << " *)other_this;\n"; - out << " }\n"; - } - } - out << " else {\n"; - out << " return nullptr;\n"; - out << " }\n"; - if (has_self_member(struct_type)) { - out << " PyObject *stored_self = to_this->__self__;\n"; - out << " if (stored_self == nullptr) {\n"; - out << " // Allocate a new Python instance\n"; - out << " Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&Dtool_" << ClassName << "._PyType, 0);\n"; - out << " self->_signature = PY_PANDA_SIGNATURE;\n"; - out << " self->_My_Type = &Dtool_" << ClassName << ";\n"; - out << " self->_ptr_to_object = to_this;\n"; - out << " self->_memory_rules = true;\n"; - out << " self->_is_const = false;\n"; - out << " to_this->__self__ = Py_NewRef((PyObject *)self);\n"; - out << " return Py_NewRef((PyObject *)self);\n"; - out << " }\n"; - out << " PyObject *result = Py_NewRef(stored_self);\n"; - out << " bool nonzero = to_this->unref();\n"; - out << " nassertr(nonzero, result);\n"; - out << " return result;\n"; - } else { - out << " // Allocate a new Python instance\n"; - out << " Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&Dtool_" << ClassName << "._PyType, 0);\n"; - out << " self->_signature = PY_PANDA_SIGNATURE;\n"; - out << " self->_My_Type = &Dtool_" << ClassName << ";\n"; - out << " self->_ptr_to_object = to_this;\n"; - out << " self->_memory_rules = false;\n"; - out << " self->_is_const = false;\n"; - out << " return (PyObject *)self;\n"; - } - out << "}\n\n"; - } -} - -/** - - */ -void InterfaceMakerPythonNative:: -write_class_declarations(ostream &out, ostream *out_h, Object *obj) { - const InterrogateType &itype = obj->_itype; - std::string class_name = make_safe_name(obj->_itype.get_scoped_name()); - std::string c_class_name = obj->_itype.get_true_name(); - std::string preferred_name = itype.get_name(); - std::string class_struct_name = std::string(CLASS_PREFIX) + class_name; - - CPPType *type = obj->_itype._cpptype; - - // This typedef is necessary for class templates since we can't pass a comma - // to a macro function. - out << "typedef " << c_class_name << " " << class_name << "_localtype;\n"; - if (obj->_itype.has_destructor() || - obj->_itype.destructor_is_inherited() || - obj->_itype.destructor_is_implicit()) { - - if (TypeManager::is_reference_count(type)) { - out << "Define_Module_ClassRef"; - } else { - out << "Define_Module_Class"; - } - } else { - if (TypeManager::is_reference_count(type)) { - out << "Define_Module_ClassRef_Private"; - } else { - out << "Define_Module_Class_Private"; - } - } - out << "(" << _def->module_name << ", " << class_name << ", " << class_name << "_localtype, " << classNameFromCppName(preferred_name, false) << ");\n"; - - out << "static struct Dtool_PyTypedObject *const Dtool_Ptr_" << class_name << " = &Dtool_" << class_name << ";\n"; - out << "static void Dtool_PyModuleClassInit_" << class_name << "(PyObject *module);\n"; - - int has_coerce = has_coerce_constructor(type->as_struct_type()); - if (has_coerce > 0) { - if (TypeManager::is_reference_count(type)) { - out << "bool Dtool_ConstCoerce_" << class_name << "(PyObject *args, CPT(" << c_class_name << ") &coerced);\n"; - if (has_coerce > 1) { - out << "bool Dtool_Coerce_" << class_name << "(PyObject *args, PT(" << c_class_name << ") &coerced);\n"; - } - } else { - out << "" << c_class_name << " *Dtool_Coerce_" << class_name << "(PyObject *args, " << c_class_name << " &coerced);\n"; - } - } - - out << "\n"; - - if (out_h != nullptr) { - *out_h << "extern \"C\" " << EXPORT_IMPORT_PREFIX << " struct Dtool_PyTypedObject Dtool_" << class_name << ";\n"; - } -} - -/** - * Generates whatever additional code is required to support a module file. - */ -void InterfaceMakerPythonNative:: -write_sub_module(ostream &out, Object *obj) { - // Object * obj = _objects[_embeded_index] ; - string class_name = make_safe_name(obj->_itype.get_scoped_name()); - string class_ptr; - - if (!obj->_itype.is_typedef()) { - out << " // " << *(obj->_itype._cpptype) << "\n"; - out << " Dtool_PyModuleClassInit_" << class_name << "(module);\n"; - class_ptr = "&Dtool_" + class_name; - - } else { - // Unwrap typedefs. - TypeIndex wrapped = obj->_itype._wrapped_type; - while (interrogate_type_is_typedef(wrapped)) { - wrapped = interrogate_type_wrapped_type(wrapped); - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &wrapped_itype = idb->get_type(wrapped); - - class_name = make_safe_name(wrapped_itype.get_scoped_name()); - - out << " // typedef " << wrapped_itype.get_scoped_name() - << " " << *(obj->_itype._cpptype) << "\n"; - - if (!isExportThisRun(wrapped_itype._cpptype)) { - _external_imports.insert(TypeManager::resolve_type(wrapped_itype._cpptype)); - - class_ptr = "Dtool_Ptr_" + class_name; - out << " assert(" << class_ptr << " != nullptr);\n"; - } else { - class_ptr = "&Dtool_" + class_name; - - // If this is a typedef to a class defined in the same module, make sure - // that the class is initialized before we try to define the typedef. - out << " Dtool_PyModuleClassInit_" << class_name << "(module);\n"; - } - } - - std::string export_class_name = classNameFromCppName(obj->_itype.get_name(), false); - std::string export_class_name2 = classNameFromCppName(obj->_itype.get_name(), true); - - class_ptr = "(PyObject *)" + class_ptr; - - // The first time we add something to a module, we use PyModule_AddObject, - // which steals a reference. This saves a call to Py_DECREF. - if (!obj->_itype.is_typedef()) { - out << " PyModule_AddObject(module, \"" << export_class_name << "\", " << class_ptr << ");\n"; - } else { - out << " PyModule_AddObjectRef(module, \"" << export_class_name << "\", " << class_ptr << ");\n"; - } - if (export_class_name != export_class_name2) { - out << " PyModule_AddObjectRef(module, \"" << export_class_name2 << "\", " << class_ptr << ");\n"; - } -} - -/** - - */ -void InterfaceMakerPythonNative:: -write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { - out << "/**\n"; - out << " * Module Object Linker ..\n"; - out << " */\n"; - - Objects::iterator oi; - - out << "void Dtool_" << def->library_name << "_RegisterTypes() {\n" - " TypeRegistry *registry = TypeRegistry::ptr();\n" - " nassertv(registry != nullptr);\n"; - - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - if (object->_itype.is_class() || object->_itype.is_struct()) { - CPPType *type = object->_itype._cpptype; - if (is_cpp_type_legal(type) && isExportThisRun(type)) { - string class_name = object->_itype.get_scoped_name(); - string safe_name = make_safe_name(class_name); - bool is_typed = has_get_class_type_function(type); - - if (is_typed) { - out << " {\n"; - if (has_init_type_function(type)) { - // Call the init_type function. This isn't necessary for all - // types as many of them are automatically initialized at static - // init type, but for some extension classes it's useful. - out << " " << type->get_local_name(&parser) - << "::init_type();\n"; - } - out << " TypeHandle handle = " << type->get_local_name(&parser) - << "::get_class_type();\n"; - out << " Dtool_" << safe_name << "._type = handle;\n"; - out << " registry->record_python_type(handle," - " &Dtool_" << safe_name << "._PyType," - " Dtool_Wrap_" << safe_name << ");\n"; - out << " }\n"; - } else { - if (IsPandaTypedObject(type->as_struct_type())) { - nout << object->_itype.get_scoped_name() << " derives from TypedObject, " - << "but does not define a get_class_type() function.\n"; - } - } - } - } - } - out << "}\n\n"; - - out << "void Dtool_" << def->library_name << "_BuildInstants(PyObject *module) {\n"; - out << " (void) module;\n"; - - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - if (object->_itype.is_enum() && !object->_itype.is_nested() && - isExportThisRun(object->_itype._cpptype)) { - int enum_count = object->_itype.number_of_enum_values(); - - if (object->_itype.is_scoped_enum()) { - // Convert as Python 3.4-style enum. - string class_name = object->_itype._cpptype->get_local_name(&parser); - string safe_name = make_safe_name(class_name); - - CPPType *underlying_type = TypeManager::unwrap_const(object->_itype._cpptype->as_enum_type()->get_underlying_type()); - string cast_to = underlying_type->get_local_name(&parser); - out << " // enum class " << object->_itype.get_scoped_name() << "\n"; - out << " {\n"; - out << " PyObject *members = PyTuple_New(" << enum_count << ");\n"; - out << " PyObject *member;\n"; - for (int xx = 0; xx < enum_count; xx++) { - out << " member = PyTuple_New(2);\n" - "#if PY_MAJOR_VERSION >= 3\n" - " PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\"" - << object->_itype.get_enum_value_name(xx) << "\"));\n" - "#else\n" - " PyTuple_SET_ITEM(member, 0, PyString_FromString(\"" - << object->_itype.get_enum_value_name(xx) << "\"));\n" - "#endif\n" - " PyTuple_SET_ITEM(member, 1, Dtool_WrapValue((" - << cast_to << ")" << object->_itype.get_scoped_name() << "::" - << object->_itype.get_enum_value_name(xx) << "));\n" - " PyTuple_SET_ITEM(members, " << xx << ", member);\n"; - } - out << " Dtool_Ptr_" << safe_name << " = Dtool_EnumType_Create(\"" - << object->_itype.get_name() << "\", members, \"" - << _def->module_name << "\");\n"; - out << " PyModule_AddObject(module, \"" << object->_itype.get_name() - << "\", (PyObject *)Dtool_Ptr_" << safe_name << ");\n"; - out << " }\n"; - } else { - out << " // enum " << object->_itype.get_scoped_name() << "\n"; - for (int xx = 0; xx < enum_count; xx++) { - string name1 = classNameFromCppName(object->_itype.get_enum_value_name(xx), false); - string name2 = classNameFromCppName(object->_itype.get_enum_value_name(xx), true); - string enum_value = "::" + object->_itype.get_enum_value_name(xx); - out << " PyModule_AddObject(module, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n"; - if (name1 != name2) { - // Also write the mangled name, for historical purposes. - out << " PyModule_AddObject(module, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n"; - } - } - } - } - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - int num_manifests = idb->get_num_global_manifests(); - for (int mi = 0; mi < num_manifests; mi++) { - ManifestIndex manifest_index = idb->get_global_manifest(mi); - const InterrogateManifest &iman = idb->get_manifest(manifest_index); - if (iman.has_getter()) { - FunctionIndex func_index = iman.get_getter(); - record_function(dummy_type, func_index); - } - - string name1 = classNameFromCppName(iman.get_name(), false); - string name2 = classNameFromCppName(iman.get_name(), true); - if (iman.has_int_value()) { - int value = iman.get_int_value(); - out << " PyModule_AddIntConstant(module, \"" << name1 << "\", " << value << ");\n"; - if (name1 != name2) { - // Also write the mangled name, for historical purposes. - out << " PyModule_AddIntConstant(module, \"" << name2 << "\", " << value << ");\n"; - } - } else { - string value = iman.get_definition(); - out << " PyModule_AddStringConstant(module, \"" << name1 << "\", \"" << value << "\");\n"; - if (name1 != name2) { - out << " PyModule_AddStringConstant(module, \"" << name2 << "\", \"" << value << "\");\n"; - } - } - } - - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - if (!object->_itype.get_outer_class()) { - if (object->_itype.is_class() || - object->_itype.is_struct() || - object->_itype.is_typedef()) { - if (is_cpp_type_legal(object->_itype._cpptype)) { - if (isExportThisRun(object->_itype._cpptype)) { - write_sub_module(out, object); - } - } - } - } - } - - out << "}\n\n"; - - bool force_base_functions = true; - - out << "static PyMethodDef python_simple_funcs[] = {\n"; - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - if (!func->_itype.is_global() && is_function_legal(func)) { - string name1 = methodNameFromCppName(func, "", false); - string name2 = methodNameFromCppName(func, "", true); - - string flags; - string fptr = "&" + func->_name; - switch (func->_args_type) { - case AT_keyword_args: - flags = "METH_VARARGS | METH_KEYWORDS"; - fptr = "(PyCFunction) " + fptr; - break; - - case AT_varargs: - flags = "METH_VARARGS"; - break; - - case AT_single_arg: - flags = "METH_O"; - break; - - default: - flags = "METH_NOARGS"; - break; - } - - // Note: we shouldn't add METH_STATIC here, since both METH_STATIC and - // METH_CLASS are illegal for module-level functions. - - out << " {\"" << name1 << "\", " << fptr - << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; - if (name1 != name2) { - out << " {\"" << name2 << "\", " << fptr - << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; - } - } - } - - if (force_base_functions) { - out << " // Support Function For Dtool_types ... for now in each module ??\n"; - out << " {\"Dtool_BorrowThisReference\", &Dtool_BorrowThisReference, METH_VARARGS, \"Used to borrow 'this' pointer (to, from)\\nAssumes no ownership.\"},\n"; - //out << " {\"Dtool_AddToDictionary\", &Dtool_AddToDictionary, METH_VARARGS, \"Used to add items into a tp_dict\"},\n"; - } - - out << " {nullptr, nullptr, 0, nullptr}\n" << "};\n\n"; - - if (_external_imports.empty()) { - out << "extern const struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, exports, nullptr};\n"; - } else { - out << - "#ifdef LINK_ALL_STATIC\n" - "extern const struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, exports, nullptr};\n" - "#else\n" - "extern const struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, exports, imports};\n" - "#endif\n"; - } - if (out_h != nullptr) { - *out_h << "extern const struct LibraryDef " << def->library_name << "_moddef;\n"; - } -} - -/** - - */ -void InterfaceMakerPythonNative:: -write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) { - InterfaceMakerPython::write_module(out, out_h, def); - Objects::iterator oi; - - out << "/**\n"; - out << " * Module initialization functions for Python module \"" << def->module_name << "\"\n"; - out << " */\n"; - - out << "#if PY_MAJOR_VERSION >= 3\n" - << "static struct PyModuleDef python_native_module = {\n" - << " PyModuleDef_HEAD_INIT,\n" - << " \"" << def->module_name << "\",\n" - << " nullptr,\n" - << " -1,\n" - << " nullptr,\n" - << " nullptr, nullptr, nullptr, nullptr\n" - << "};\n" - << "\n" - << "extern \"C\" EXPORT_CLASS PyObject *PyInit_" << def->module_name << "();\n" - << "\n" - << "PyObject *PyInit_" << def->module_name << "() {\n" - << " LibraryDef *refs[] = {&" << def->library_name << "_moddef, nullptr};\n" - << " PyObject *module = Dtool_PyModuleInitHelper(refs, &python_native_module);\n" - << " Dtool_" << def->library_name << "_BuildInstants(module);\n" - << " return module;\n" - << "}\n" - << "\n" - << "#else // Python 2 case\n" - << "\n" - << "extern \"C\" EXPORT_CLASS void init" << def->module_name << "();\n" - << "\n" - << "void init" << def->module_name << "() {\n" - << " LibraryDef *refs[] = {&" << def->library_name << "_moddef, nullptr};\n" - << " PyObject *module = Dtool_PyModuleInitHelper(refs, \"" << def->module_name << "\");\n" - << " Dtool_" << def->library_name << "_BuildInstants(module);\n" - << "}\n" - << "\n" - << "#endif\n" - << "\n"; -} -/** - - */ -void InterfaceMakerPythonNative:: -write_module_class(ostream &out, Object *obj) { - bool has_local_repr = false; - bool has_local_str = false; - bool has_local_richcompare = false; - bool has_local_getbuffer = false; - - { - int num_nested = obj->_itype.number_of_nested_types(); - for (int ni = 0; ni < num_nested; ni++) { - TypeIndex nested_index = obj->_itype.get_nested_type(ni); - if (_objects.count(nested_index) == 0) { - // Illegal type. - continue; - } - - Object *nested_obj = _objects[nested_index]; - assert(nested_obj != nullptr); - - if (nested_obj->_itype.is_class() || nested_obj->_itype.is_struct()) { - write_module_class(out, nested_obj); - } - } - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - std::string cClassName = obj->_itype.get_true_name(); - std::string export_class_name = classNameFromCppName(obj->_itype.get_name(), false); - - CPPStructType *struct_type = obj->_itype._cpptype->as_struct_type(); - bool py_subclassable = is_python_subclassable(struct_type); - - out << "/**\n"; - out << " * Python method tables for " << ClassName << " (" << export_class_name << ")\n" ; - out << " */\n"; - out << "static PyMethodDef Dtool_Methods_" << ClassName << "[] = {\n"; - - SlottedFunctions slots; - // function Table - bool got_copy = false; - bool got_deepcopy = false; - - for (Function *func : obj->_methods) { - if (func->_name == "__copy__") { - got_copy = true; - } else if (func->_name == "__deepcopy__") { - got_deepcopy = true; - } - - string name1 = methodNameFromCppName(func, export_class_name, false); - string name2 = methodNameFromCppName(func, export_class_name, true); - - string flags; - string fptr = "&" + func->_name; - switch (func->_args_type) { - case AT_keyword_args: - flags = "METH_VARARGS | METH_KEYWORDS"; - fptr = "(PyCFunction) " + fptr; - break; - - case AT_varargs: - flags = "METH_VARARGS"; - break; - - case AT_single_arg: - flags = "METH_O"; - break; - - default: - flags = "METH_NOARGS"; - break; - } - - if (!func->_has_this) { - if (func->_flags & FunctionRemap::F_explicit_cls) { - flags += " | METH_CLASS"; - } else { - flags += " | METH_STATIC"; - } - - // Skip adding this entry if we also have a property with the same name. - // In that case, we will use a Dtool_StaticProperty to disambiguate - // access to this method. See GitHub issue #444. - for (const Property *property : obj->_properties) { - if (property->_has_this && - property->_ielement.get_name() == func->_ifunc.get_name()) { - continue; - } - } - } - - bool has_nonslotted = false; - - for (FunctionRemap *remap : func->_remaps) { - if (!is_remap_legal(remap)) { - continue; - } - - SlottedFunctionDef slotted_def; - - if (get_slotted_function_def(obj, func, remap, slotted_def)) { - const string &key = slotted_def._answer_location; - if (slotted_def._wrapper_type == WT_none) { - slotted_def._wrapper_name = func->_name; - } else { - slotted_def._wrapper_name = func->_name + "_" + key; - } - if (slots.count(key)) { - slots[key]._remaps.insert(remap); - } else { - slots[key] = slotted_def; - slots[key]._remaps.insert(remap); - } - if (slotted_def._keep_method) { - has_nonslotted = true; - } - - // Python 3 doesn't support nb_divide. It has nb_true_divide and also - // nb_floor_divide, but they have different semantics than in C++. - // Ugh. Make special slots to store the nb_divide members that don't - // take an int. We'll use this to build up nb_true_divide, in the - // absence of a custom __truediv__, so that we can still properly divide - // float vector types. - if ((key == "nb_divide" || key == "nb_inplace_divide") && - (remap->_flags & FunctionRemap::F_divide_integer) == 0) { - string true_key; - if (key == "nb_inplace_divide") { - true_key = "nb_inplace_true_divide"; - } else { - true_key = "nb_true_divide"; - } - if (slots.count(true_key) == 0) { - SlottedFunctionDef def; - def._answer_location = true_key; - def._wrapper_type = slotted_def._wrapper_type; - def._wrapper_name = func->_name + "_" + true_key; - slots[true_key] = def; - } - slots[true_key]._remaps.insert(remap); - } - } else { - has_nonslotted = true; - } - } - - if (has_nonslotted) { - // This is a bit of a hack, as these methods should probably be going - // through the slotted function system. But it's kind of pointless to - // write these out, and a waste of space. - string fname = func->_ifunc.get_name(); - if (fname == "operator <" || - fname == "operator <=" || - fname == "operator ==" || - fname == "operator !=" || - fname == "operator >" || - fname == "operator >=" || - fname == "operator <=>") { - continue; - } - - // This method has non-slotted remaps, so write it out into the function - // table. - out << " {\"" << name1 << "\", " << fptr - << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; - if (name1 != name2) { - out << " {\"" << name2 << "\", " << fptr - << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; - } - } - } - - if (obj->_protocol_types & Object::PT_make_copy) { - if (!got_copy) { - out << " {\"__copy__\", ©_from_make_copy, METH_NOARGS, nullptr},\n"; - got_copy = true; - } - } else if (obj->_protocol_types & Object::PT_copy_constructor) { - if (!got_copy) { - out << " {\"__copy__\", ©_from_copy_constructor, METH_NOARGS, nullptr},\n"; - got_copy = true; - } - } - - if (got_copy && !got_deepcopy) { - out << " {\"__deepcopy__\", &map_deepcopy_to_copy, METH_VARARGS, nullptr},\n"; - } - - for (MakeSeq *make_seq : obj->_make_seqs) { - if (!is_function_legal(make_seq->_length_getter) || - !is_function_legal(make_seq->_element_getter)) { - continue; - } - - string seq_name = make_seq->_imake_seq.get_name(); - - string flags = "METH_NOARGS"; - if (!make_seq->_length_getter->_has_this && - !make_seq->_element_getter->_has_this) { - flags += " | METH_STATIC"; - } - - string name1 = methodNameFromCppName(seq_name, export_class_name, false); - string name2 = methodNameFromCppName(seq_name, export_class_name, true); - out << " {\"" << name1 - << "\", (PyCFunction) &" << make_seq->_name << ", " << flags << ", nullptr},\n"; - if (name1 != name2) { - out << " { \"" << name2 - << "\", (PyCFunction) &" << make_seq->_name << ", " << flags << ", nullptr},\n"; - } - } - - out << " {nullptr, nullptr, 0, nullptr}\n" - << "};\n\n"; - - int num_derivations = obj->_itype.number_of_derivations(); - int di; - for (di = 0; di < num_derivations; di++) { - TypeIndex d_type_Index = obj->_itype.get_derivation(di); - if (!interrogate_type_is_unpublished(d_type_Index)) { - const InterrogateType &d_itype = idb->get_type(d_type_Index); - if (is_cpp_type_legal(d_itype._cpptype)) { - if (!isExportThisRun(d_itype._cpptype)) { - _external_imports.insert(TypeManager::resolve_type(d_itype._cpptype)); - - // out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << - // make_safe_name(d_itype.get_scoped_name().c_str()) << ";\n"; - } - } - } - } - - std::vector bases; - for (di = 0; di < num_derivations; di++) { - TypeIndex d_type_Index = obj->_itype.get_derivation(di); - if (!interrogate_type_is_unpublished(d_type_Index)) { - const InterrogateType &d_itype = idb->get_type(d_type_Index); - if (is_cpp_type_legal(d_itype._cpptype)) { - bases.push_back(d_itype._cpptype); - } - } - } - - { - SlottedFunctions::iterator rfi; - for (rfi = slots.begin(); rfi != slots.end(); rfi++) { - const SlottedFunctionDef &def = rfi->second; - - // This is just for reporting. There might be remaps from multiple - // functions with different names mapped to the same slot. - string fname; - if (def._remaps.size() > 0) { - const FunctionRemap *first_remap = *def._remaps.begin(); - fname = first_remap->_cppfunc->get_simple_name(); - } - - if (def._min_version > 0) { - out << "#if PY_VERSION_HEX >= 0x" << hex << def._min_version << dec << "\n"; - } - - switch (rfi->second._wrapper_type) { - case WT_no_params: - case WT_iter_next: - // PyObject *func(PyObject *self) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static PyObject *" << def._wrapper_name << "(PyObject *self) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - - int return_flags = RF_pyobject | RF_err_null; - if (rfi->second._wrapper_type == WT_iter_next) { - // If the function returns NULL, we should return NULL to indicate - // a StopIteration, rather than returning None. - return_flags |= RF_preserve_null; - } - string expected_params; - if (!write_function_forset(out, def._remaps, 0, 0, expected_params, 2, true, true, - AT_no_args, return_flags, false)) { - error_bad_args_return(out, 2, return_flags, expected_params); - } - out << "}\n\n"; - } - break; - - case WT_one_param: - // PyObject *func(PyObject *self, PyObject *one) - { - bool all_nonconst = true; - for (FunctionRemap *remap : def._remaps) { - if (remap->_const_method) { - all_nonconst = false; - } - } - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - if (all_nonconst) { - out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" - << ClassName << ", (void **)&local_this, \"" << ClassName - << "." << methodNameFromCppName(fname, "", false) << "\")) {\n"; - out << " return nullptr;\n"; - } else { - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - } - out << " }\n"; - - string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_err_null | RF_pyobject, false, !all_nonconst); - - error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); - out << "}\n\n"; - } - break; - - case WT_binary_operator: - case WT_inplace_binary_operator: - // PyObject *func(PyObject *self, PyObject *one) - { - int return_flags = RF_err_null; - if (rfi->second._wrapper_type == WT_inplace_binary_operator) { - return_flags |= RF_self; - } else { - return_flags |= RF_pyobject; - } - bool forward_all_nonconst = true; - bool reverse_all_nonconst = true; - set forward_remaps; - set reverse_remaps; - for (FunctionRemap *remap : def._remaps) { - std::string fname = remap->_cppfunc->get_simple_name(); - if (fname.compare(0, 3, "__r") == 0 && fname != "__rshift__") { - reverse_remaps.insert(remap); - if (remap->_const_method) { - reverse_all_nonconst = false; - } - } else { - forward_remaps.insert(remap); - if (remap->_const_method) { - forward_all_nonconst = false; - } - } - } - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - // WT_binary_operator means we must return NotImplemented, instead - // of raising an exception, if the this pointer doesn't match. - // This is for things like __sub__, which Python likes to call on - // the wrong-type objects. - if (!forward_remaps.empty()) { - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; - if (forward_all_nonconst) { - out << " if (local_this != nullptr && !DtoolInstance_IS_CONST(self)) {\n"; - } else { - out << " if (local_this != nullptr) {\n"; - } - string expected_params; - write_function_forset(out, forward_remaps, 1, 1, expected_params, 4, true, true, - AT_single_arg, return_flags, false, !forward_all_nonconst); - out << " }\n"; - } - - if (!reverse_remaps.empty()) { - out << " std::swap(self, arg);\n"; - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; - if (reverse_all_nonconst) { - out << " if (local_this != nullptr && !DtoolInstance_IS_CONST(self)) {\n"; - } else { - out << " if (local_this != nullptr) {\n"; - } - string expected_params; - write_function_forset(out, reverse_remaps, 1, 1, expected_params, 4, true, true, - AT_single_arg, return_flags, false, !reverse_all_nonconst); - out << " }\n"; - } - - out << " return Py_NewRef(Py_NotImplemented);\n"; - out << "}\n\n"; - } - break; - - case WT_setattr: - // int func(PyObject *self, PyObject *one, PyObject *two = NULL) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - set setattr_remaps; - set delattr_remaps; - - // This function handles both delattr and setattr. Fish out the - // remaps for both types. - for (FunctionRemap *remap : def._remaps) { - if (remap->_cppfunc->get_simple_name() == "__delattr__" && remap->_parameters.size() == 2) { - delattr_remaps.insert(remap); - - } else if (remap->_cppfunc->get_simple_name() == "__setattr__" && remap->_parameters.size() == 3) { - setattr_remaps.insert(remap); - } - } - - out << " // Determine whether to call __setattr__ or __delattr__.\n"; - out << " if (arg2 != nullptr) { // __setattr__\n"; - - if (!setattr_remaps.empty()) { - out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - string expected_params; - if (!write_function_forset(out, setattr_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_int | RF_decref_args, true)) { - error_bad_args_return(out, 4, RF_int | RF_decref_args, expected_params); - } - } else { - out << " PyErr_Format(PyExc_TypeError,\n"; - out << " \"can't set attributes of built-in/extension type '%s'\",\n"; - out << " Py_TYPE(self)->tp_name);\n"; - out << " return -1;\n\n"; - } - - out << " } else { // __delattr__\n"; - - if (!delattr_remaps.empty()) { - string expected_params; - if (!write_function_forset(out, delattr_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, true)) { - error_bad_args_return(out, 4, RF_int | RF_decref_args, expected_params); - } - } else { - out << " PyErr_Format(PyExc_TypeError,\n"; - out << " \"can't delete attributes of built-in/extension type '%s'\",\n"; - out << " Py_TYPE(self)->tp_name);\n"; - out << " return -1;\n"; - } - out << " }\n"; - - out << "}\n\n"; - } - break; - - case WT_getattr: - // PyObject *func(PyObject *self, PyObject *one) Specifically to - // implement __getattr__. First calls PyObject_GenericGetAttr(), and - // only calls the wrapper if it returns NULL. If one wants to override - // this completely, one should define __getattribute__ instead. - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; - out << " PyObject *res = PyObject_GenericGetAttr(self, arg);\n"; - out << " if (res != nullptr) {\n"; - out << " return res;\n"; - out << " }\n"; - out << " if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {\n"; - out << " return nullptr;\n"; - out << " }\n"; - out << " PyErr_Clear();\n\n"; - - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - - string expected_params; - if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, - true, true, AT_single_arg, - RF_pyobject | RF_err_null, true)) { - // out << " PyErr_Clear();\n"; - out << " return nullptr;\n"; - } - out << "}\n\n"; - } - break; - - case WT_sequence_getitem: - // PyObject *func(PyObject *self, Py_ssize_t index) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static PyObject *" << def._wrapper_name << "(PyObject *self, Py_ssize_t index) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - - // This is a getitem or setitem of a sequence type. This means we - // *need* to raise IndexError if we're out of bounds. We have to - // assume the bounds are 0 .. this->size() (this is the same - // assumption that Python makes). - out << " if (index < 0 || index >= (Py_ssize_t) local_this->size()) {\n"; - out << "#ifdef NDEBUG\n"; - out << " PyErr_SetString(PyExc_IndexError, \"index out of range\");\n"; - out << "#else\n"; - out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << " index out of range\");\n"; - out << "#endif\n"; - out << " return nullptr;\n"; - out << " }\n"; - - string expected_params; - if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { - error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); - } - out << "}\n\n"; - } - break; - - case WT_sequence_setitem: - // int_t func(PyObject *self, Py_ssize_t index, PyObject *value) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self, Py_ssize_t index, PyObject *arg) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - out << " if (index < 0 || index >= (Py_ssize_t) local_this->size()) {\n"; - out << "#ifdef NDEBUG\n"; - out << " PyErr_SetString(PyExc_IndexError, \"index out of range\");\n"; - out << "#else\n"; - out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << " index out of range\");\n"; - out << "#endif\n"; - out << " return -1;\n"; - out << " }\n"; - - set setitem_remaps; - set delitem_remaps; - - // This function handles both delitem and setitem. Fish out the - // remaps for either one. - for (FunctionRemap *remap : def._remaps) { - if (remap->_flags & FunctionRemap::F_setitem_int) { - setitem_remaps.insert(remap); - - } else if (remap->_flags & FunctionRemap::F_delitem_int) { - delitem_remaps.insert(remap); - } - } - - string expected_params; - bool always_returns = true; - out << " if (arg != nullptr) { // __setitem__\n"; - if (!write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, - true, true, AT_single_arg, RF_int, false, true, "index")) { - always_returns = false; - } - out << " } else { // __delitem__\n"; - if (!write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, false, true, "index")) { - always_returns = false; - } - out << " }\n\n"; - - if (!always_returns) { - error_bad_args_return(out, 2, RF_int, expected_params); - } - out << "}\n\n"; - } - break; - - case WT_sequence_size: - // Py_ssize_t func(PyObject *self) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static Py_ssize_t " << def._wrapper_name << "(PyObject *self) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - // This is a cheap cheat around all of the overhead of calling the - // wrapper function. - out << " return (Py_ssize_t) local_this->" << fname << "();\n"; - out << "}\n\n"; - } - break; - - case WT_mapping_setitem: - // int func(PyObject *self, PyObject *one, PyObject *two) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - set setitem_remaps; - set delitem_remaps; - - // This function handles both delitem and setitem. Fish out the - // remaps for either one. - for (FunctionRemap *remap : def._remaps) { - if (remap->_flags & FunctionRemap::F_setitem) { - setitem_remaps.insert(remap); - - } else if (remap->_flags & FunctionRemap::F_delitem) { - delitem_remaps.insert(remap); - } - } - - string expected_params; - bool always_returns = true; - out << " if (arg2 != nullptr) { // __setitem__\n"; - if (setitem_remaps.empty()) { - always_returns = false; - } else { - out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - if (!write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_int | RF_decref_args, false)) { - always_returns = false; - } - out << " Py_DECREF(args);\n"; - } - out << " } else { // __delitem__\n"; - if (!write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, false)) { - always_returns = false; - } - out << " }\n\n"; - - if (!always_returns) { - error_bad_args_return(out, 2, RF_int, expected_params); - } - out << "}\n\n"; - } - break; - - case WT_inquiry: - // int func(PyObject *self) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self) {\n"; - - // Find the remap. There should be only one. - FunctionRemap *remap = *def._remaps.begin(); - const char *container = ""; - - if (remap->_has_this) { - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - container = "local_this"; - } - - vector_string params; - out << " return (int) " << remap->call_function(out, 4, false, container, params) << ";\n"; - out << "}\n\n"; - } - break; - - case WT_getbuffer: - // int __getbuffer__(PyObject *self, Py_buffer *buffer, int flags) We - // map this directly, and assume that the arguments match. The whole - // point of this is to be fast, and we don't want to negate that by - // first wrapping and then unwrapping the arguments again. We also - // want to guarantee const correctness, since that will determine - // whether a read-only buffer is given. - { - has_local_getbuffer = true; - - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self, Py_buffer *buffer, int flags) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - vector_string params_const(1); - vector_string params_nonconst(1); - FunctionRemap *remap_const = nullptr; - FunctionRemap *remap_nonconst = nullptr; - - // Iterate through the remaps to find the one that matches our - // parameters. - for (FunctionRemap *remap : def._remaps) { - if (remap->_const_method) { - if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { - params_const.push_back("self"); - } - remap_const = remap; - } else { - if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { - params_nonconst.push_back("self"); - } - remap_nonconst = remap; - } - } - params_const.push_back("buffer"); - params_const.push_back("flags"); - params_nonconst.push_back("buffer"); - params_nonconst.push_back("flags"); - - // We have to distinguish properly between const and nonconst, - // because the function may depend on it to decide whether to - // provide a writable buffer or a readonly buffer. - const string const_this = "(const " + cClassName + " *)local_this"; - if (remap_const != nullptr && remap_nonconst != nullptr) { - out << " if (!DtoolInstance_IS_CONST(self)) {\n"; - out << " return " << remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst) << ";\n"; - out << " } else {\n"; - out << " return " << remap_const->call_function(out, 4, false, const_this, params_const) << ";\n"; - out << " }\n"; - } else if (remap_nonconst != nullptr) { - out << " if (!DtoolInstance_IS_CONST(self)) {\n"; - out << " return " << remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst) << ";\n"; - out << " } else {\n"; - out << " Dtool_Raise_TypeError(\"Cannot call " << ClassName << ".__getbuffer__() on a const object.\");\n"; - out << " return -1;\n"; - out << " }\n"; - } else if (remap_const != nullptr) { - out << " return " << remap_const->call_function(out, 4, false, const_this, params_const) << ";\n"; - } else { - nout << ClassName << "::__getbuffer__ does not match the required signature.\n"; - out << " return -1;\n"; - } - - out << "}\n\n"; - } - break; - - case WT_releasebuffer: - // void __releasebuffer__(PyObject *self, Py_buffer *buffer) Same - // story as __getbuffer__ above. - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static void " << def._wrapper_name << "(PyObject *self, Py_buffer *buffer) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return;\n"; - out << " }\n\n"; - - vector_string params_const(1); - vector_string params_nonconst(1); - FunctionRemap *remap_const = nullptr; - FunctionRemap *remap_nonconst = nullptr; - - // Iterate through the remaps to find the one that matches our - // parameters. - for (FunctionRemap *remap : def._remaps) { - if (remap->_const_method) { - if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { - params_const.push_back("self"); - } - remap_const = remap; - } else { - if ((remap->_flags & FunctionRemap::F_explicit_self) == 0) { - params_nonconst.push_back("self"); - } - remap_nonconst = remap; - } - } - params_const.push_back("buffer"); - params_nonconst.push_back("buffer"); - - string return_expr; - const string const_this = "(const " + cClassName + " *)local_this"; - if (remap_const != nullptr && remap_nonconst != nullptr) { - out << " if (!DtoolInstance_IS_CONST(self)) {\n"; - return_expr = remap_nonconst->call_function(out, 4, false, "local_this", params_nonconst); - if (!return_expr.empty()) { - out << " " << return_expr << ";\n"; - } - out << " } else {\n"; - return_expr = remap_const->call_function(out, 4, false, const_this, params_const); - - if (!return_expr.empty()) { - out << " " << return_expr << ";\n"; - } - out << " }\n"; - - } else if (remap_nonconst != nullptr) { - // Doesn't matter if there's no const version. We *have* to call - // it or else we could leak memory. - return_expr = remap_nonconst->call_function(out, 2, false, "local_this", params_nonconst); - if (!return_expr.empty()) { - out << " " << return_expr << ";\n"; - } - - } else if (remap_const != nullptr) { - return_expr = remap_const->call_function(out, 2, false, const_this, params_const); - if (!return_expr.empty()) { - out << " " << return_expr << ";\n"; - } - - } else { - nout << ClassName << "::__releasebuffer__ does not match the required signature.\n"; - out << " return;\n"; - } - - out << "}\n\n"; - } - break; - - case WT_ternary_operator: - case WT_inplace_ternary_operator: - // PyObject *func(PyObject *self, PyObject *one, PyObject *two) - { - int return_flags = RF_err_null; - if (rfi->second._wrapper_type == WT_inplace_ternary_operator) { - return_flags |= RF_self; - } else { - return_flags |= RF_pyobject; - } - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static PyObject *" << def._wrapper_name << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; - out << " if (local_this == nullptr) {\n"; - // WT_ternary_operator means we must return NotImplemented, instead - // of raising an exception, if the this pointer doesn't match. This - // is for things like __pow__, which Python likes to call on the - // wrong-type objects. - out << " return Py_NewRef(Py_NotImplemented);\n"; - out << " }\n"; - - set one_param_remaps; - set two_param_remaps; - - for (FunctionRemap *remap : def._remaps) { - if (remap->_parameters.size() == 2) { - one_param_remaps.insert(remap); - - } else if (remap->_parameters.size() == 3) { - two_param_remaps.insert(remap); - } - } - - string expected_params; - bool always_returns = true; - out << " if (arg2 != nullptr && arg2 != Py_None) {\n"; - if (two_param_remaps.empty()) { - always_returns = false; - } else { - out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - if (!write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, return_flags | RF_decref_args, true)) { - always_returns = false; - } - out << " Py_DECREF(args);\n"; - } - out << " } else {\n"; - if (!write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, return_flags, true)) { - always_returns = false; - } - out << " }\n\n"; - - if (!always_returns) { - error_bad_args_return(out, 2, return_flags, expected_params); - } - out << "}\n\n"; - } - break; - - case WT_traverse: - // int __traverse__(PyObject *self, visitproc visit, void *arg) This - // is a low-level function. Overloads are not supported. - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self, visitproc visit, void *arg) {\n"; - - // Find the remap. There should be only one. - FunctionRemap *remap = *def._remaps.begin(); - - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; - out << " if (local_this == nullptr) {\n"; - out << " return 0;\n"; - out << " }\n\n"; - - // Only participate in cycle detection if there are no C++ - // references to this object. - out << " if (local_this->get_ref_count() != (int)((Dtool_PyInstDef *)self)->_memory_rules) {\n"; - out << " return 0;\n"; - out << " }\n\n"; - - if (py_subclassable) { - // Python-subclassable types store a reference to their Python - // wrapper. - if (struct_type->is_final()) { - out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType) {\n"; - } else { - out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType && DtoolInstance_TYPE(self) == &Dtool_" << ClassName << ") {\n"; - } - out << " Py_VISIT(self);\n"; - out << " }\n"; - } - - vector_string params((int)remap->_has_this); - params.push_back("visit"); - params.push_back("arg"); - - out << " return " << remap->call_function(out, 2, false, "local_this", params) << ";\n"; - out << "}\n\n"; - } - break; - - case WT_compare: - // int func(PyObject *self, Py_ssize_t index) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static int " << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - string expected_params; - if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_compare, false, true)) { - error_bad_args_return(out, 2, RF_int, expected_params); - } - out << "}\n\n"; - } - break; - - case WT_hash: - // Py_hash_t func(PyObject *self) - { - out << "//////////////////\n"; - out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; - out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; - out << "//////////////////\n"; - out << "static Py_hash_t " << def._wrapper_name << "(PyObject *self) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - - FunctionRemap *remap = *def._remaps.begin(); - vector_string params; - out << " return (Py_hash_t) " << remap->call_function(out, 4, false, "local_this", params) << ";\n"; - out << "}\n\n"; - } - break; - - case WT_new: - { - string fname = "static PyObject *" + def._wrapper_name + "(PyTypeObject *cls, PyObject *args, PyObject *kwds)\n"; - - std::vector remaps; - remaps.insert(remaps.end(), def._remaps.begin(), def._remaps.end()); - string expected_params; - write_function_for_name(out, obj, remaps, fname, expected_params, true, AT_keyword_args, RF_pyobject | RF_err_null); - } - break; - - case WT_none: - // Nothing special about the wrapper function: just write it normally. - string fname = "static PyObject *" + def._wrapper_name + "(PyObject *self, PyObject *args, PyObject *kwds)\n"; - - std::vector remaps; - remaps.insert(remaps.end(), def._remaps.begin(), def._remaps.end()); - string expected_params; - write_function_for_name(out, obj, remaps, fname, expected_params, true, AT_keyword_args, RF_pyobject | RF_err_null); - break; - } - - if (def._min_version > 0) { - out << "#endif // PY_VERSION_HEX >= 0x" << hex << def._min_version << dec << "\n"; - } - } - - int need_repr = 0; - if (slots.count("tp_repr") == 0) { - need_repr = NeedsAReprFunction(obj->_itype); - } - if (need_repr > 0) { - out << "//////////////////\n"; - out << "// A __repr__ function\n"; - out << "// " << ClassName << "\n"; - out << "//////////////////\n"; - out << "static PyObject *Dtool_Repr_" << ClassName << "(PyObject *self) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - out << " std::ostringstream os;\n"; - if (need_repr == 3) { - out << " invoke_extension(local_this).python_repr(os, \"" - << classNameFromCppName(ClassName, false) << "\");\n"; - } else if (need_repr == 2) { - out << " local_this->output(os);\n"; - } else { - out << " local_this->python_repr(os, \"" - << classNameFromCppName(ClassName, false) << "\");\n"; - } - out << " std::string ss = os.str();\n"; - out << " return Dtool_WrapValue(ss);\n"; - out << "}\n\n"; - has_local_repr = true; - } - - int need_str = 0; - if (slots.count("tp_str") == 0) { - need_str = NeedsAStrFunction(obj->_itype); - } - if (need_str > 0) { - out << "//////////////////\n"; - out << "// A __str__ function\n"; - out << "// " << ClassName << "\n"; - out << "//////////////////\n"; - out << "static PyObject *Dtool_Str_" << ClassName << "(PyObject *self) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - out << " std::ostringstream os;\n"; - if (need_str == 2) { - out << " local_this->write(os, 0);\n"; - } else { - out << " local_this->write(os);\n"; - } - out << " std::string ss = os.str();\n"; - out << " return Dtool_WrapValue(ss);\n"; - out << "}\n\n"; - has_local_str = true; - } - } - - if (NeedsARichCompareFunction(obj->_itype) || slots.count("tp_compare")) { - out << "//////////////////\n"; - out << "// A rich comparison function\n"; - out << "// " << ClassName << "\n"; - out << "//////////////////\n"; - out << "static PyObject *Dtool_RichCompare_" << ClassName << "(PyObject *self, PyObject *arg, int op) {\n"; - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - - std::set threeway_remaps; - bool have_eq = false; - bool have_ne = false; - for (Function *func : obj->_methods) { - std::set remaps; - if (!func) { - continue; - } - // We only accept comparison operators that take one parameter (besides - // 'this'). - for (FunctionRemap *remap : func->_remaps) { - if (is_remap_legal(remap) && remap->_has_this && (remap->_args_type == AT_single_arg)) { - remaps.insert(remap); - } - } - const string &fname = func->_ifunc.get_name(); - const char *op_type; - if (fname == "operator <") { - op_type = "Py_LT"; - } else if (fname == "operator <=") { - op_type = "Py_LE"; - } else if (fname == "operator ==") { - op_type = "Py_EQ"; - have_eq = true; - } else if (fname == "operator !=") { - op_type = "Py_NE"; - have_ne = true; - } else if (fname == "operator >") { - op_type = "Py_GT"; - } else if (fname == "operator >=") { - op_type = "Py_GE"; - } else if (fname == "operator <=>") { - threeway_remaps = std::move(remaps); - continue; - } else { - continue; - } - if (!has_local_richcompare) { - out << " switch (op) {\n"; - has_local_richcompare = true; - } - out << " case " << op_type << ":\n"; - - out << " {\n"; - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_pyobject | RF_err_null, false)) { - out << " break;\n"; - } - out << " }\n"; - } - - if (has_local_richcompare) { - if (!threeway_remaps.empty()) { - out << " default:\n"; - out << " {\n"; - string expected_params; - write_function_forset(out, threeway_remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_richcompare_zero | RF_err_null, false); - out << " }\n"; - } - else if (have_eq && !have_ne) { - // Generate a not-equal function from the equal function. - for (Function *func : obj->_methods) { - std::set remaps; - if (!func) { - continue; - } - const string &fname = func->_ifunc.get_name(); - if (fname != "operator ==") { - continue; - } - for (FunctionRemap *remap : func->_remaps) { - if (is_remap_legal(remap) && remap->_has_this && (remap->_args_type == AT_single_arg)) { - remaps.insert(remap); - } - } - out << " case Py_NE: // from Py_EQ\n"; - out << " {\n"; - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_pyobject | RF_invert_bool | RF_err_null, false)) { - out << " break;\n"; - } - out << " }\n"; - } - } - else if (!have_eq && !slots.count("tp_compare")) { - // Generate an equals function. - out << " case Py_EQ:\n"; - out << " return PyBool_FromLong(DtoolInstance_Check(arg) && DtoolInstance_VOID_PTR(self) == DtoolInstance_VOID_PTR(arg));\n"; - if (!have_ne) { - out << " case Py_NE:\n"; - out << " return PyBool_FromLong(!DtoolInstance_Check(arg) || DtoolInstance_VOID_PTR(self) != DtoolInstance_VOID_PTR(arg));\n"; - } - } - - // End of switch block - out << " }\n\n"; - out << " if (PyErr_Occurred()) {\n"; - out << " PyErr_Clear();\n"; - out << " }\n\n"; - } - else if (!threeway_remaps.empty()) { - string expected_params; - write_function_forset(out, threeway_remaps, 1, 1, expected_params, 2, true, false, - AT_single_arg, RF_richcompare_zero | RF_err_null, false); - } - - if (slots.count("tp_compare") && threeway_remaps.empty()) { - // A lot of Panda code depends on comparisons being done via the - // compare_to function, which is mapped to the tp_compare slot, which - // Python 3 no longer has. So, we'll write code to fall back to that if - // no matching comparison operator was found. - out << " // All is not lost; we still have the compare_to function to fall back onto.\n"; - out << " int cmpval = " << slots["tp_compare"]._wrapper_name << "(self, arg);\n"; - out << " if (cmpval == -1 && PyErr_Occurred()) {\n"; - out << " if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; - out << " PyErr_Clear();\n"; - out << " } else {\n"; - out << " return nullptr;\n"; - out << " }\n"; - out << " }\n"; - out << " switch (op) {\n"; - out << " case Py_LT:\n"; - out << " return PyBool_FromLong(cmpval < 0);\n"; - out << " case Py_LE:\n"; - out << " return PyBool_FromLong(cmpval <= 0);\n"; - out << " case Py_EQ:\n"; - out << " return PyBool_FromLong(cmpval == 0);\n"; - out << " case Py_NE:\n"; - out << " return PyBool_FromLong(cmpval != 0);\n"; - out << " case Py_GT:\n"; - out << " return PyBool_FromLong(cmpval > 0);\n"; - out << " case Py_GE:\n"; - out << " return PyBool_FromLong(cmpval >= 0);\n"; - out << " }\n"; - has_local_richcompare = true; - } - - out << " return Py_NewRef(Py_NotImplemented);\n"; - out << "}\n\n"; - } - - bool has_gc = (slots.count("tp_traverse") || has_self_member(struct_type)); - bool has_local_traverse = false; - bool has_local_clear = false; - if (py_subclassable || has_gc) { - // Note that in the case of py_subclassable, the traverse function will - // only be called if the class is subclassed from Python, since we don't - // set Py_TPFLAGS_HAVE_GC, so we don't need to check whether it's a proxy. - if (!slots.count("tp_traverse")) { - has_local_traverse = true; - out << "static int Dtool_Traverse_" << ClassName << "(PyObject *self, visitproc visit, void *arg) {\n"; - out << " // If the only reference remaining is the one held by the Python wrapper,\n"; - out << " // report the circular reference to Python's GC, so that it can break it.\n"; - out << " " << cClassName << " *local_this;\n"; - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void**)(&local_this));\n"; - out << " if (local_this == nullptr) {\n"; - out << " return 0;\n"; - out << " }\n"; - out << " if (local_this->get_ref_count() == (int)((Dtool_PyInstDef *)self)->_memory_rules) {\n"; - if (py_subclassable) { - out << " Py_VISIT(self);\n"; - } - if (has_self_member(struct_type)) { - out << " Py_VISIT(local_this->__self__);\n"; - } - out << " }\n"; - out << " return 0;\n"; - out << "}\n"; - out << "\n"; - } - - if (!slots.count("tp_clear")) { - has_local_clear = true; - out << "static int Dtool_Clear_" << ClassName << "(PyObject *self) {\n"; - if (has_self_member(struct_type)) { - out << " Py_CLEAR(local_this->__self__);\n"; - } - if (py_subclassable) { - if (struct_type->is_final()) { - out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType) {\n"; - } else { - out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType && DtoolInstance_TYPE(self) == &Dtool_" << ClassName << ") {\n"; - } - out << " DtoolProxy_" << ClassName << " *proxy = (DtoolProxy_" << ClassName << " *)DtoolInstance_VOID_PTR(self);\n"; - out << " Py_CLEAR(proxy->DtoolProxy::_self);\n"; - out << " }\n"; - } - out << " return 0;\n"; - out << "}\n\n"; - } - } - - int num_getset = 0; - - if (obj->_properties.size() > 0) { - // Write out the array of properties, telling Python which getter and - // setter to call when they are assigned or queried in Python code. - for (Property *property : obj->_properties) { - const InterrogateElement &ielem = property->_ielement; - if (!property->_has_this || property->_getter_remaps.empty()) { - continue; - } - - // Actually, if we have a conflicting static method with the same name, - // we will need to use Dtool_StaticProperty instead. - for (const Function *func : obj->_methods) { - if (!func->_has_this && func->_ifunc.get_name() == ielem.get_name()) { - continue; - } - } - - if (num_getset == 0) { - out << "static PyGetSetDef Dtool_Properties_" << ClassName << "[] = {\n"; - } - - ++num_getset; - - string name1 = methodNameFromCppName(ielem.get_name(), "", false); - // string name2 = methodNameFromCppName(ielem.get_name(), "", true); - - string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter"; - string setter = "nullptr"; - if (!ielem.is_sequence() && !ielem.is_mapping() && !property->_setter_remaps.empty()) { - setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter"; - } - - out << " {(char *)\"" << name1 << "\", " << getter << ", " << setter; - - if (ielem.has_comment()) { - out << ", (char *)\n"; - output_quoted(out, 4, ielem.get_comment()); - out << ",\n "; - } else { - out << ", nullptr, "; - } - - // Extra void* argument; we don't make use of it. - out << "nullptr},\n"; - - /*if (name1 != name2 && name1 != "__dict__") { - // Add alternative spelling. - out << " {(char *)\"" << name2 << "\", " << getter << ", " << setter - << ", (char *)\n" - << " \"Alias of " << name1 << ", for consistency with old naming conventions.\",\n" - << " NULL},\n"; - }*/ - } - - if (num_getset != 0) { - out << " {nullptr},\n"; - out << "};\n\n"; - } - } - - // These fields are inherited together. We should either write all of them - // or none of them so that they are inherited from DTOOL_SUPER_BASE. - bool has_hash_compare = (slots.count("tp_hash") != 0 || - slots.count("tp_compare") != 0 || - has_local_richcompare); - - bool has_parent_class = (obj->_itype.number_of_derivations() != 0); - - // Output the type slot tables. - out << "static PyNumberMethods Dtool_NumberMethods_" << ClassName << " = {\n"; - write_function_slot(out, 2, slots, "nb_add"); - write_function_slot(out, 2, slots, "nb_subtract"); - write_function_slot(out, 2, slots, "nb_multiply"); - out << "#if PY_MAJOR_VERSION < 3\n"; - // Note: nb_divide does not exist in Python 3. We will probably need some - // smart mechanism for dispatching to either floor_divide or true_divide. - write_function_slot(out, 2, slots, "nb_divide"); - out << "#endif\n"; - write_function_slot(out, 2, slots, "nb_remainder"); - write_function_slot(out, 2, slots, "nb_divmod"); - write_function_slot(out, 2, slots, "nb_power"); - write_function_slot(out, 2, slots, "nb_negative"); - write_function_slot(out, 2, slots, "nb_positive"); - write_function_slot(out, 2, slots, "nb_absolute"); - write_function_slot(out, 2, slots, "nb_bool"); - write_function_slot(out, 2, slots, "nb_invert"); - write_function_slot(out, 2, slots, "nb_lshift"); - write_function_slot(out, 2, slots, "nb_rshift"); - write_function_slot(out, 2, slots, "nb_and"); - write_function_slot(out, 2, slots, "nb_xor"); - write_function_slot(out, 2, slots, "nb_or"); - out << "#if PY_MAJOR_VERSION < 3\n"; - write_function_slot(out, 2, slots, "nb_coerce"); - out << "#endif\n"; - write_function_slot(out, 2, slots, "nb_int"); - out << " nullptr, // nb_long\n"; // removed in Python 3 - write_function_slot(out, 2, slots, "nb_float"); - out << "#if PY_MAJOR_VERSION < 3\n"; - write_function_slot(out, 2, slots, "nb_oct"); - write_function_slot(out, 2, slots, "nb_hex"); - out << "#endif\n"; - - write_function_slot(out, 2, slots, "nb_inplace_add"); - write_function_slot(out, 2, slots, "nb_inplace_subtract"); - write_function_slot(out, 2, slots, "nb_inplace_multiply"); - out << "#if PY_MAJOR_VERSION < 3\n"; - write_function_slot(out, 2, slots, "nb_inplace_divide"); - out << "#endif\n"; - write_function_slot(out, 2, slots, "nb_inplace_remainder"); - write_function_slot(out, 2, slots, "nb_inplace_power"); - write_function_slot(out, 2, slots, "nb_inplace_lshift"); - write_function_slot(out, 2, slots, "nb_inplace_rshift"); - write_function_slot(out, 2, slots, "nb_inplace_and"); - write_function_slot(out, 2, slots, "nb_inplace_xor"); - write_function_slot(out, 2, slots, "nb_inplace_or"); - - write_function_slot(out, 2, slots, "nb_floor_divide"); - write_function_slot(out, 2, slots, "nb_true_divide"); - write_function_slot(out, 2, slots, "nb_inplace_floor_divide"); - write_function_slot(out, 2, slots, "nb_inplace_true_divide"); - - out << "#if PY_VERSION_HEX >= 0x02050000\n"; - write_function_slot(out, 2, slots, "nb_index"); - out << "#endif\n"; - - out << "#if PY_VERSION_HEX >= 0x03050000\n"; - write_function_slot(out, 2, slots, "nb_matrix_multiply"); - write_function_slot(out, 2, slots, "nb_inplace_matrix_multiply"); - out << "#endif\n"; - - out << "};\n\n"; - - // NB: it's tempting not to write this table when a class doesn't have them. - // But then Python won't inherit them from base classes either! So we - // always write this table for now even if it will be full of 0's, unless - // this type has no base classes at all. - if (has_parent_class || (obj->_protocol_types & Object::PT_sequence) != 0) { - out << "static PySequenceMethods Dtool_SequenceMethods_" << ClassName << " = {\n"; - write_function_slot(out, 2, slots, "sq_length"); - write_function_slot(out, 2, slots, "sq_concat"); - write_function_slot(out, 2, slots, "sq_repeat"); - write_function_slot(out, 2, slots, "sq_item"); - out << " nullptr, // sq_slice\n"; // removed in Python 3 - write_function_slot(out, 2, slots, "sq_ass_item"); - out << " nullptr, // sq_ass_slice\n"; // removed in Python 3 - write_function_slot(out, 2, slots, "sq_contains"); - - write_function_slot(out, 2, slots, "sq_inplace_concat"); - write_function_slot(out, 2, slots, "sq_inplace_repeat"); - out << "};\n\n"; - } - - // Same note applies as for the SequenceMethods. - if (has_parent_class || (obj->_protocol_types & Object::PT_mapping) != 0) { - out << "static PyMappingMethods Dtool_MappingMethods_" << ClassName << " = {\n"; - write_function_slot(out, 2, slots, "mp_length"); - write_function_slot(out, 2, slots, "mp_subscript"); - write_function_slot(out, 2, slots, "mp_ass_subscript"); - out << "};\n\n"; - } - - // Same note applies as above. - if (has_parent_class || has_local_getbuffer) { - out << "static PyBufferProcs Dtool_BufferProcs_" << ClassName << " = {\n"; - out << "#if PY_MAJOR_VERSION < 3\n"; - write_function_slot(out, 2, slots, "bf_getreadbuffer"); - write_function_slot(out, 2, slots, "bf_getwritebuffer"); - write_function_slot(out, 2, slots, "bf_getsegcount"); - write_function_slot(out, 2, slots, "bf_getcharbuffer"); - out << "#endif\n"; - out << "#if PY_VERSION_HEX >= 0x02060000\n"; - write_function_slot(out, 2, slots, "bf_getbuffer"); - write_function_slot(out, 2, slots, "bf_releasebuffer"); - out << "#endif\n"; - out << "};\n\n"; - } - - bool have_async = false; - if (has_parent_class || slots.count("am_await") != 0 || - slots.count("am_aiter") != 0 || - slots.count("am_anext") != 0) { - out << "#if PY_VERSION_HEX >= 0x03050000\n"; - out << "static PyAsyncMethods Dtool_AsyncMethods_" << ClassName << " = {\n"; - write_function_slot(out, 2, slots, "am_await"); - write_function_slot(out, 2, slots, "am_aiter"); - write_function_slot(out, 2, slots, "am_anext"); - out << "};\n"; - out << "#endif\n\n"; - have_async = true; - } - - // Output the actual PyTypeObject definition. - out << "struct Dtool_PyTypedObject Dtool_" << ClassName << " = {\n"; - out << " {\n"; - out << " PyVarObject_HEAD_INIT(nullptr, 0)\n"; - // const char *tp_name; - out << " \"" << _def->module_name << "." << export_class_name << "\",\n"; - // Py_ssize_t tp_basicsize; - out << " 0, // tp_basicsize\n"; // inherited from tp_base - // Py_ssize_t tp_itemsize; - out << " 0, // tp_itemsize\n"; - - // destructor tp_dealloc; - out << " &Dtool_FreeInstance_" << ClassName << ",\n"; - - out << "#if PY_VERSION_HEX >= 0x03080000\n"; - out << " 0, // tp_vectorcall_offset\n"; - out << "#else\n"; - write_function_slot(out, 4, slots, "tp_print"); - out << "#endif\n"; - - // getattrfunc tp_getattr; - write_function_slot(out, 4, slots, "tp_getattr"); - // setattrfunc tp_setattr; - write_function_slot(out, 4, slots, "tp_setattr"); - - // cmpfunc tp_compare; (reserved in Python 3) - out << "#if PY_VERSION_HEX >= 0x03050000\n"; - if (have_async) { - out << " &Dtool_AsyncMethods_" << ClassName << ",\n"; - } else { - out << " nullptr, // tp_as_async\n"; - } - out << "#elif PY_MAJOR_VERSION >= 3\n"; - out << " nullptr, // tp_reserved\n"; - out << "#else\n"; - if (has_hash_compare) { - write_function_slot(out, 4, slots, "tp_compare", - "&DtoolInstance_ComparePointers"); - } else { - out << " nullptr, // tp_compare\n"; - } - out << "#endif\n"; - - // reprfunc tp_repr; - if (has_local_repr) { - out << " &Dtool_Repr_" << ClassName << ",\n"; - } else { - write_function_slot(out, 4, slots, "tp_repr"); - } - - // PyNumberMethods *tp_as_number; - out << " &Dtool_NumberMethods_" << ClassName << ",\n"; - // PySequenceMethods *tp_as_sequence; - if (has_parent_class || (obj->_protocol_types & Object::PT_sequence) != 0) { - out << " &Dtool_SequenceMethods_" << ClassName << ",\n"; - } else { - out << " nullptr, // tp_as_sequence\n"; - } - // PyMappingMethods *tp_as_mapping; - if (has_parent_class || (obj->_protocol_types & Object::PT_mapping) != 0) { - out << " &Dtool_MappingMethods_" << ClassName << ",\n"; - } else { - out << " nullptr, // tp_as_mapping\n"; - } - - // hashfunc tp_hash; - if (has_hash_compare) { - write_function_slot(out, 4, slots, "tp_hash", "&DtoolInstance_HashPointer"); - } else { - out << " nullptr, // tp_hash\n"; - } - - // ternaryfunc tp_call; - write_function_slot(out, 4, slots, "tp_call"); - - // reprfunc tp_str; - if (has_local_str) { - out << " &Dtool_Str_" << ClassName << ",\n"; - } else if (has_local_repr) { - out << " &Dtool_Repr_" << ClassName << ",\n"; - } else { - write_function_slot(out, 4, slots, "tp_str"); - } - - // getattrofunc tp_getattro; - write_function_slot(out, 4, slots, "tp_getattro"); - // setattrofunc tp_setattro; - write_function_slot(out, 4, slots, "tp_setattro"); - - // PyBufferProcs *tp_as_buffer; - if (has_parent_class || has_local_getbuffer) { - out << " &Dtool_BufferProcs_" << ClassName << ",\n"; - } else { - out << " nullptr, // tp_as_buffer\n"; - } - - string gcflag; - if (has_gc && slots.count("tp_traverse")) { - gcflag = " | Py_TPFLAGS_HAVE_GC"; - } - - // long tp_flags; - if (has_local_getbuffer) { - out << "#if PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x03000000\n"; - out << " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_NEWBUFFER" << gcflag << ",\n"; - out << "#else\n"; - out << " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES" << gcflag << ",\n"; - out << "#endif\n"; - } else { - out << " Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES" << gcflag << ",\n"; - } - - // const char *tp_doc; - if (obj->_itype.has_comment()) { - out << "#ifdef NDEBUG\n"; - out << " 0,\n"; - out << "#else\n"; - output_quoted(out, 4, obj->_itype.get_comment()); - out << ",\n"; - out << "#endif\n"; - } else { - out << " nullptr, // tp_doc\n"; - } - - // traverseproc tp_traverse; - if (has_local_traverse) { - out << " &Dtool_Traverse_" << ClassName << ",\n"; - } else if (has_gc) { - write_function_slot(out, 4, slots, "tp_traverse"); - } else { - out << " nullptr, // tp_traverse\n"; - } - - // inquiry tp_clear; - if (has_local_clear) { - out << " &Dtool_Clear_" << ClassName << ",\n"; - } else if (has_gc) { - write_function_slot(out, 4, slots, "tp_clear"); - } else { - out << " nullptr, // tp_clear\n"; - } - - // richcmpfunc tp_richcompare; - if (has_local_richcompare) { - out << " &Dtool_RichCompare_" << ClassName << ",\n"; - } else if (has_hash_compare) { - // All hashable types need to be comparable. - out << "#if PY_MAJOR_VERSION >= 3\n"; - out << " &DtoolInstance_RichComparePointers,\n"; - out << "#else\n"; - out << " nullptr, // tp_richcompare\n"; - out << "#endif\n"; - } else { - out << " nullptr, // tp_richcompare\n"; - } - - // Py_ssize_t tp_weaklistoffset; - out << " 0, // tp_weaklistoffset\n"; - - // getiterfunc tp_iter; - write_function_slot(out, 4, slots, "tp_iter"); - // iternextfunc tp_iternext; - write_function_slot(out, 4, slots, "tp_iternext"); - - // struct PyMethodDef *tp_methods; - out << " Dtool_Methods_" << ClassName << ",\n"; - // struct PyMemberDef *tp_members; - out << " nullptr, // tp_members\n"; - - // struct PyGetSetDef *tp_getset; - if (num_getset > 0) { - out << " Dtool_Properties_" << ClassName << ",\n"; - } else { - out << " nullptr, // tp_getset\n"; - } - - // struct _typeobject *tp_base; - out << " nullptr, // tp_base\n"; - // PyObject *tp_dict; - out << " nullptr, // tp_dict\n"; - // descrgetfunc tp_descr_get; - write_function_slot(out, 4, slots, "tp_descr_get"); - // descrsetfunc tp_descr_set; - write_function_slot(out, 4, slots, "tp_descr_set"); - // Py_ssize_t tp_dictoffset; - out << " 0, // tp_dictoffset\n"; - // initproc tp_init; - out << " Dtool_Init_" << ClassName << ",\n"; - // allocfunc tp_alloc; - out << " PyType_GenericAlloc,\n"; - // newfunc tp_new; - write_function_slot(out, 4, slots, "tp_new", "Dtool_new_" + ClassName); - // freefunc tp_free; - if (slots.count("tp_traverse") || has_self_member(struct_type)) { - out << " PyObject_GC_Del,\n"; - } else { - out << " PyObject_Del,\n"; - } - // inquiry tp_is_gc; - out << " nullptr, // tp_is_gc\n"; - // PyObject *tp_bases; - out << " nullptr, // tp_bases\n"; - // PyObject *tp_mro; - out << " nullptr, // tp_mro\n"; - // PyObject *tp_cache; - out << " nullptr, // tp_cache\n"; - // PyObject *tp_subclasses; - out << " nullptr, // tp_subclasses\n"; - // PyObject *tp_weaklist; - out << " nullptr, // tp_weaklist\n"; - // destructor tp_del; - out << " nullptr, // tp_del\n"; - // unsigned int tp_version_tag - out << "#if PY_VERSION_HEX >= 0x02060000\n"; - out << " 0, // tp_version_tag\n"; - out << "#endif\n"; - // destructor tp_finalize - out << "#if PY_VERSION_HEX >= 0x03040000\n"; - out << " nullptr, // tp_finalize\n"; - out << "#endif\n"; - // vectorcallfunc tp_vectorcall - out << "#if PY_VERSION_HEX >= 0x03080000\n"; - out << " nullptr, // tp_vectorcall\n"; - out << "#endif\n"; - out << " },\n"; - - // It's tempting to initialize the type handle here, but this causes static - // init ordering issues; this may run before init_type is called. - out << " TypeHandle::none(),\n"; - out << " Dtool_PyModuleClassInit_" << ClassName << ",\n"; - out << " Dtool_UpcastInterface_" << ClassName << ",\n"; - out << " Dtool_Wrap_" << ClassName << ",\n"; - - int has_coerce = has_coerce_constructor(struct_type); - if (has_coerce > 0) { - if (TypeManager::is_reference_count(struct_type)) { - out << " (CoerceFunction)Dtool_ConstCoerce_" << ClassName << ",\n"; - if (has_coerce > 1) { - out << " (CoerceFunction)Dtool_Coerce_" << ClassName << ",\n"; - } else { - out << " nullptr,\n"; - } - } else { - out << " nullptr,\n"; - out << " (CoerceFunction)Dtool_Coerce_" << ClassName << ",\n"; - } - } else { - out << " nullptr,\n"; - out << " nullptr,\n"; - } - - out << "};\n\n"; - - out << "static void Dtool_PyModuleClassInit_" << ClassName << "(PyObject *module) {\n"; - out << " (void) module; // Unused\n"; - out << " static bool initdone = false;\n"; - out << " if (!initdone) {\n"; - out << " initdone = true;\n"; - - // Add bases. - out << " // Dependent objects\n"; - if (bases.size() > 0) { - string baseargs; - for (CPPType *base : bases) { - string safe_name = make_safe_name(base->get_local_name(&parser)); - - if (isExportThisRun(base)) { - baseargs += ", (PyTypeObject *)&Dtool_" + safe_name; - out << " Dtool_PyModuleClassInit_" << safe_name << "(nullptr);\n"; - - } else { - baseargs += ", (PyTypeObject *)Dtool_Ptr_" + safe_name; - - out << " assert(Dtool_Ptr_" << safe_name << " != nullptr);\n" - << " assert(Dtool_Ptr_" << safe_name << "->_Dtool_ModuleClassInit != nullptr);\n" - << " Dtool_Ptr_" << safe_name << "->_Dtool_ModuleClassInit(nullptr);\n"; - } - } - - out << " Dtool_" << ClassName << "._PyType.tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n"; - } - out << " Dtool_" << ClassName << "._PyType.tp_base = (PyTypeObject *)Dtool_GetSuperBase();\n"; - - int num_nested = obj->_itype.number_of_nested_types(); - int num_dict_items = 1; - - // Go through once to estimate the number of elements the dict will hold. - for (int ni = 0; ni < num_nested; ni++) { - TypeIndex nested_index = obj->_itype.get_nested_type(ni); - if (_objects.count(nested_index) == 0) { - continue; - } - Object *nested_obj = _objects[nested_index]; - assert(nested_obj != nullptr); - - if (nested_obj->_itype.is_class() || nested_obj->_itype.is_struct()) { - num_dict_items += 2; - - } else if (nested_obj->_itype.is_typedef()) { - ++num_dict_items; - - } else if (nested_obj->_itype.is_enum() && !nested_obj->_itype.is_scoped_enum()) { - CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type(); - num_dict_items += 2 * enum_type->_elements.size(); - } - } - - // Build type dictionary. The size is just an estimation. - if (num_dict_items > 5) { - out << " PyObject *dict = _PyDict_NewPresized(" << num_dict_items << ");\n"; - } else { - out << " PyObject *dict = PyDict_New();\n"; - } - out << " Dtool_" << ClassName << "._PyType.tp_dict = dict;\n"; - out << " PyDict_SetItemString(dict, \"DtoolClassDict\", dict);\n"; - - // Now go through the nested types again to actually add the dict items. - for (int ni = 0; ni < num_nested; ni++) { - TypeIndex nested_index = obj->_itype.get_nested_type(ni); - if (_objects.count(nested_index) == 0) { - // Illegal type. - continue; - } - - Object *nested_obj = _objects[nested_index]; - assert(nested_obj != nullptr); - - if (nested_obj->_itype.is_class() || nested_obj->_itype.is_struct()) { - std::string ClassName1 = make_safe_name(nested_obj->_itype.get_scoped_name()); - std::string ClassName2 = make_safe_name(nested_obj->_itype.get_name()); - out << " // Nested Object " << ClassName1 << ";\n"; - out << " Dtool_PyModuleClassInit_" << ClassName1 << "(nullptr);\n"; - string name1 = classNameFromCppName(ClassName2, false); - string name2 = classNameFromCppName(ClassName2, true); - out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ");\n"; - if (name1 != name2) { - out << " PyDict_SetItemString(dict, \"" << name2 << "\", (PyObject *)&Dtool_" << ClassName1 << ");\n"; - } - - } else if (nested_obj->_itype.is_typedef()) { - // Unwrap typedefs. - TypeIndex wrapped = nested_obj->_itype._wrapped_type; - while (interrogate_type_is_typedef(wrapped)) { - wrapped = interrogate_type_wrapped_type(wrapped); - } - - // Er, we can only export typedefs to structs. - if (!interrogate_type_is_struct(wrapped)) { - continue; - } - - string ClassName1 = make_safe_name(interrogate_type_scoped_name(wrapped)); - string ClassName2 = make_safe_name(interrogate_type_name(wrapped)); - - string name1 = classNameFromCppName(ClassName2, false); - out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ");\n"; - // No need to support mangled names for nested typedefs; we only added - // support recently. - - } else if (nested_obj->_itype.is_scoped_enum()) { - // Convert enum class as Python 3.4-style enum. - string class_name = nested_obj->_itype._cpptype->get_local_name(&parser); - string safe_name = make_safe_name(class_name); - - int enum_count = nested_obj->_itype.number_of_enum_values(); - CPPType *underlying_type = TypeManager::unwrap_const(nested_obj->_itype._cpptype->as_enum_type()->get_underlying_type()); - string cast_to = underlying_type->get_local_name(&parser); - out << " // enum class " << nested_obj->_itype.get_scoped_name() << ";\n"; - out << " {\n"; - out << " PyObject *members = PyTuple_New(" << enum_count << ");\n"; - out << " PyObject *member;\n"; - for (int xx = 0; xx < enum_count; xx++) { - out << " member = PyTuple_New(2);\n" - "#if PY_MAJOR_VERSION >= 3\n" - " PyTuple_SET_ITEM(member, 0, PyUnicode_FromString(\"" - << nested_obj->_itype.get_enum_value_name(xx) << "\"));\n" - "#else\n" - " PyTuple_SET_ITEM(member, 0, PyString_FromString(\"" - << nested_obj->_itype.get_enum_value_name(xx) << "\"));\n" - "#endif\n" - " PyTuple_SET_ITEM(member, 1, Dtool_WrapValue((" - << cast_to << ")" << nested_obj->_itype.get_scoped_name() << "::" - << nested_obj->_itype.get_enum_value_name(xx) << "));\n" - " PyTuple_SET_ITEM(members, " << xx << ", member);\n"; - } - out << " Dtool_Ptr_" << safe_name << " = Dtool_EnumType_Create(\"" - << nested_obj->_itype.get_name() << "\", members, \"" - << _def->module_name << "\");\n"; - out << " PyDict_SetItemString(dict, \"" << nested_obj->_itype.get_name() - << "\", (PyObject *)Dtool_Ptr_" << safe_name << ");\n"; - out << " }\n"; - - } else if (nested_obj->_itype.is_enum()) { - out << " // enum " << nested_obj->_itype.get_scoped_name() << ";\n"; - CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type(); - CPPEnumType::Elements::const_iterator ei; - for (ei = enum_type->_elements.begin(); ei != enum_type->_elements.end(); ++ei) { - string name1 = classNameFromCppName((*ei)->get_simple_name(), false); - string name2; - if (nested_obj->_itype.has_true_name()) { - name2 = classNameFromCppName((*ei)->get_simple_name(), true); - } else { - // Don't generate the alternative syntax for anonymous enums, since - // we added support for those after we started deprecating the - // alternative syntax. - name2 = name1; - } - string enum_value = obj->_itype.get_scoped_name() + "::" + (*ei)->get_simple_name(); - out << " PyDict_SetItemString(dict, \"" << name1 << "\", Dtool_WrapValue(" << enum_value << "));\n"; - if (name1 != name2) { - out << " PyDict_SetItemString(dict, \"" << name2 << "\", Dtool_WrapValue(" << enum_value << "));\n"; - } - } - } - } - - // Also add the static properties, which can't be added via getset. - for (Property *property : obj->_properties) { - const InterrogateElement &ielem = property->_ielement; - if (property->_getter_remaps.empty()) { - continue; - } - if (property->_has_this) { - // Actually, continue if we have a conflicting static method with the - // same name, which may still require use of Dtool_StaticProperty. - bool have_shadow = false; - for (const Function *func : obj->_methods) { - if (!func->_has_this && func->_ifunc.get_name() == ielem.get_name()) { - have_shadow = true; - break; - } - } - if (!have_shadow) { - continue; - } - } - - string name1 = methodNameFromCppName(ielem.get_name(), "", false); - // string name2 = methodNameFromCppName(ielem.get_name(), "", true); - - string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter"; - string setter = "nullptr"; - if (!ielem.is_sequence() && !ielem.is_mapping() && !property->_setter_remaps.empty()) { - setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter"; - } - - out << " static const PyGetSetDef def_" << name1 << " = {(char *)\"" << name1 << "\", " << getter << ", " << setter; - - if (ielem.has_comment()) { - out << ", (char *)\n"; - output_quoted(out, 4, ielem.get_comment()); - out << ",\n "; - } else { - out << ", nullptr, "; - } - - // Extra void* argument; we don't make use of it. - out << "nullptr};\n"; - - out << " PyDict_SetItemString(dict, \"" << name1 << "\", Dtool_NewStaticProperty(&Dtool_" << ClassName << "._PyType, &def_" << name1 << "));\n"; - /* Alternative spelling: - out << " PyDict_SetItemString(\"" << name2 << "\", &def_" << name1 << ");\n"; - */ - } - - out << " if (PyType_Ready((PyTypeObject *)&Dtool_" << ClassName << ") < 0) {\n" - " PyErr_Format(PyExc_TypeError, \"PyType_Ready(%s)\", \"" << ClassName << "\");\n" - " return;\n" - " }\n" - " Py_INCREF((PyTypeObject *)&Dtool_" << ClassName << ");\n" - " }\n"; - -/* - * Also write out the explicit alternate names. int num_alt_names = - * obj->_itype.get_num_alt_names(); for (int i = 0; i < num_alt_names; ++i) { - * string alt_name = make_safe_name(obj->_itype.get_alt_name(i)); if - * (export_class_name != alt_name) { out << " PyModule_AddObject(module, - * \"" << alt_name << "\", (PyObject *)&Dtool_" << ClassName << - * ".As_PyTypeObject());\n"; } } - */ - - // out << " }\n"; - out << "}\n\n"; -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require the implicit "this" parameter, if present, to be - * passed as the first parameter to any wrapper functions. - */ -bool InterfaceMakerPythonNative:: -synthesize_this_parameter() { - return true; -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require overloaded instances of a function to be defined as - * separate functions (each with its own hashed name), or false for interfaces - * that can support overloading natively, and thus only require one wrapper - * function per each overloaded input function. - */ -bool InterfaceMakerPythonNative:: -separate_overloading() { - // We used to return true here. Nowadays, some of the default arguments are - // handled in the PyArg_ParseTuple code, and some are still being considered - // as separate overloads (this depends on a bunch of factors, see - // collapse_default_remaps). This is all handled elsewhere. - return false; -} - -/** - * Returns the prefix string used to generate wrapper function names. - */ -string InterfaceMakerPythonNative:: -get_wrapper_prefix() { - return "Dtool_"; -} - -/** - * Returns the prefix string used to generate unique symbolic names, which are - * not necessarily C-callable function names. - */ -string InterfaceMakerPythonNative:: -get_unique_prefix() { - return "Dtool_"; -} - -/** - * Associates the function wrapper with its function in the appropriate - * structures in the database. - */ -void InterfaceMakerPythonNative:: -record_function_wrapper(InterrogateFunction &ifunc, FunctionWrapperIndex wrapper_index) { - ifunc._python_wrappers.push_back(wrapper_index); -} - -/** - * Writes the prototype for the indicated function. - */ -void InterfaceMakerPythonNative:: -write_prototype_for(ostream &out, InterfaceMaker::Function *func) { - std::string fname = "PyObject *" + func->_name + "(PyObject *self, PyObject *args)"; - write_prototype_for_name(out, func, fname); -} -/** - * - */ -void InterfaceMakerPythonNative:: -write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std::string &function_namename) { -// Function::Remaps::const_iterator ri; - -// for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { -// FunctionRemap *remap = (*ri); - if (!output_function_names) { - // If we're not saving the function names, don't export it from the - // library. - out << "static "; - } else { - out << "extern \"C\" "; - } - out << function_namename << ";\n"; -// } -} - -/** - * Writes the definition for a function that will call the indicated C++ - * function or method. - */ -void InterfaceMakerPythonNative:: -write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func) { - - // First check if this function has non-slotted and legal remaps, ie. if we - // should even write it. - bool has_remaps = false; - - for (FunctionRemap *remap : func->_remaps) { - if (!is_remap_legal(remap)) { - continue; - } - - SlottedFunctionDef slotted_def; - if (!get_slotted_function_def(obj, func, remap, slotted_def) || slotted_def._keep_method) { - // It has a non-slotted remap, so we should write it. - has_remaps = true; - break; - } - } - - if (!has_remaps) { - // Nope. - return; - } - - // This is a bit of a hack, as these methods should probably be going - // through the slotted function system. But it's kind of pointless to write - // these out, and a waste of space. - string fname = func->_ifunc.get_name(); - if (fname == "operator <" || - fname == "operator <=" || - fname == "operator ==" || - fname == "operator !=" || - fname == "operator >" || - fname == "operator >=" || - fname == "operator <=>") { - return; - } - - if (func->_ifunc.is_unary_op()) { - assert(func->_args_type == AT_no_args); - } - - string prototype = "static PyObject *" + func->_name + "(PyObject *"; - - // This will be NULL for static funcs, so prevent code from using it. - if (func->_has_this) { - prototype += "self"; - } - else if (func->_flags & FunctionRemap::F_explicit_cls) { - prototype += "cls"; - } - - switch (func->_args_type) { - case AT_keyword_args: - prototype += ", PyObject *args, PyObject *kwds"; - break; - - case AT_varargs: - prototype += ", PyObject *args"; - break; - - case AT_single_arg: - prototype += ", PyObject *arg"; - break; - - default: - prototype += ", PyObject *"; - break; - } - prototype += ")"; - - string expected_params; - write_function_for_name(out, obj, func->_remaps, prototype, expected_params, true, func->_args_type, RF_pyobject | RF_err_null); - - // Now synthesize a variable for the docstring. - ostringstream comment; - if (!expected_params.empty()) { - comment << "C++ Interface:\n" - << expected_params; - } - - if (func->_ifunc._comment.size() > 2) { - if (!expected_params.empty()) { - comment << "\n"; - } - comment << func->_ifunc._comment; - } - - out << "#ifndef NDEBUG\n"; - out << "static const char *" << func->_name << "_comment =\n"; - output_quoted(out, 2, comment.str()); - out << ";\n"; - out << "#else\n"; - out << "static const char *" << func->_name << "_comment = nullptr;\n"; - out << "#endif\n\n"; -} - -/** - * Writes the definition for a function that will call the indicated C++ - * function or method. - */ -void InterfaceMakerPythonNative:: -write_function_for_name(ostream &out, Object *obj, - const Function::Remaps &remaps, - const string &function_name, - string &expected_params, - bool coercion_allowed, - ArgsType args_type, int return_flags) { - std::map > map_sets; - std::map >::iterator mii; - std::set::iterator sii; - - bool has_this = false; - Function::Remaps::const_iterator ri; - FunctionRemap *remap = nullptr; - int max_required_args = 0; - bool all_nonconst = true; - bool has_keywords = false; - - out << "/**\n * Python function wrapper for:\n"; - for (ri = remaps.begin(); ri != remaps.end(); ++ri) { - remap = (*ri); - if (is_remap_legal(remap)) { - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (remap->_has_this) { - has_this = true; - } - - if (!remap->_has_this || remap->_const_method) { - all_nonconst = false; - } - - if (remap->_args_type == AT_keyword_args) { - has_keywords = true; - } - - max_required_args = max(max_num_args, max_required_args); - - for (int i = min_num_args; i <= max_num_args; ++i) { - map_sets[i].insert(remap); - } - out << " * "; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - } else { - out << " * Rejected Remap ["; - remap->write_orig_prototype(out, 0); - out << "]\n"; - } - } - - out << " */\n"; - - if (has_this && obj == nullptr) { - assert(obj != nullptr); - } - - out << function_name << " {\n"; - - if (has_this) { - std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - std::string cClassName = obj->_itype.get_true_name(); - // string class_name = remap->_cpptype->get_simple_name(); - CPPStructType *struct_type = obj->_itype._cpptype->as_struct_type(); - - // If this is a non-static __setstate__, we run the default constructor. - if (remap->_cppfunc->get_local_name() == "__setstate__" && - !struct_type->is_abstract()) { - out << " " << cClassName << " *local_this = nullptr;\n" - << " if (DtoolInstance_VOID_PTR(self) == nullptr) {\n" - << " local_this = new " << cClassName << ";\n" - << " DTool_PyInit_Finalize(self, local_this, &Dtool_" << ClassName - << ", true, false);\n" - << " if (local_this == nullptr) {\n" - << " PyErr_NoMemory();\n"; - error_return(out, 6, return_flags); - out << " }\n" - << " } else if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", " - << "(void **)&local_this, \"" << classNameFromCppName(cClassName, false) - << "." << methodNameFromCppName(remap, cClassName, false) << "\")) {\n"; - } - else if (all_nonconst) { - // All remaps are non-const. Also check that this object isn't const. - out << " " << cClassName << " *local_this = nullptr;\n" - << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", " - << "(void **)&local_this, \"" << classNameFromCppName(cClassName, false) - << "." << methodNameFromCppName(remap, cClassName, false) << "\")) {\n"; - } - else { - out << " " << cClassName << " *local_this = nullptr;\n" - << " if (!DtoolInstance_GetPointer(self, local_this, Dtool_" << ClassName << ")) {\n"; - } - - error_return(out, 4, return_flags); - out << " }\n"; - } - - if (map_sets.empty()) { - error_return(out, 2, return_flags); - out << "}\n\n"; - return; - } - - if (args_type == AT_keyword_args && !has_keywords) { - // We don't actually take keyword arguments. Make sure we didn't get any. - out << " if (kwds != nullptr && PyDict_Size(kwds) > 0) {\n"; - out << "#ifdef NDEBUG\n"; - error_raise_return(out, 4, return_flags, "TypeError", "function takes no keyword arguments"); - out << "#else\n"; - error_raise_return(out, 4, return_flags, "TypeError", - methodNameFromCppName(remap, "", false) + "() takes no keyword arguments"); - out << "#endif\n"; - out << " }\n"; - args_type = AT_varargs; - } - - // If this is a __setstate__ taking multiple arguments, and we're given a - // tuple as argument, unpack it. - if (args_type == AT_single_arg && max_required_args > 1 && - remap->_cppfunc->get_local_name() == "__setstate__") { - out << " PyObject *args = arg;\n"; - args_type = AT_varargs; - } - - if (args_type == AT_keyword_args || args_type == AT_varargs) { - max_required_args = collapse_default_remaps(map_sets, max_required_args); - } - - if (remap->_flags & FunctionRemap::F_explicit_args) { - // We have a remap that wants to handle the wrapper itself. - string expected_params; - write_function_instance(out, remap, 0, 0, expected_params, 2, true, true, - args_type, return_flags); - - } else if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) { - // We have more than one remap. - switch (args_type) { - case AT_keyword_args: - indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n"; - indent(out, 2) << "if (kwds != nullptr) {\n"; - indent(out, 2) << " parameter_count += (int)PyDict_Size(kwds);\n"; - indent(out, 2) << "}\n"; - break; - - case AT_varargs: - indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n"; - break; - - case AT_single_arg: - // It shouldn't get here, but we'll handle these cases nonetheless. - indent(out, 2) << "const int parameter_count = 1;\n"; - break; - - default: - indent(out, 2) << "const int parameter_count = 0;\n"; - break; - } - - // Keep track of how many args this function actually takes for the error - // message. We add one to the parameter count for "self", following the - // Python convention. - int add_self = has_this ? 1 : 0; - set num_args; - - indent(out, 2) << "switch (parameter_count) {\n"; - for (mii = map_sets.begin(); mii != map_sets.end(); ++mii) { - int max_args = mii->first; - int min_args = min(max_required_args, max_args); - - for (int i = min_args; i <= max_args; ++i) { - indent(out, 2) << "case " << i << ":\n"; - num_args.insert(i + add_self); - } - num_args.insert(max_args + add_self); - - bool strip_keyword_args = false; - - // Check whether any remap actually takes keyword arguments. If not, - // then we don't have to bother checking that for every remap. - if (args_type == AT_keyword_args && max_args > 0) { - strip_keyword_args = true; - - std::set::iterator sii; - for (sii = mii->second.begin(); sii != mii->second.end(); ++sii) { - remap = (*sii); - size_t first_param = remap->_has_this ? 1u : 0u; - for (size_t i = first_param; i < remap->_parameters.size(); ++i) { - if (remap->_parameters[i]._has_name) { - strip_keyword_args = false; - break; - } - } - } - } - - bool always_returns; - if (strip_keyword_args) { - // None of the remaps take any keyword arguments, so let's check that - // we take none. This saves some checks later on. - indent(out, 4) << "if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) {\n"; - if (min_args == 1 && max_args == 1) { - indent(out, 4) << " PyObject *arg = PyTuple_GET_ITEM(args, 0);\n"; - always_returns = write_function_forset(out, mii->second, min_args, - max_args, expected_params, 6, - coercion_allowed, true, - AT_single_arg, return_flags, - true, !all_nonconst); - } else { - always_returns = write_function_forset(out, mii->second, min_args, - max_args, expected_params, 6, - coercion_allowed, true, - AT_varargs, return_flags, - true, !all_nonconst); - } - } else if (min_args == 1 && max_args == 1 && args_type == AT_varargs) { - // We already checked that the args tuple has only one argument, so - // we might as well extract that from the tuple now. - indent(out, 4) << "{\n"; - indent(out, 4) << " PyObject *arg = PyTuple_GET_ITEM(args, 0);\n"; - - always_returns = write_function_forset(out, mii->second, min_args, - max_args, expected_params, 6, - coercion_allowed, true, - AT_single_arg, return_flags, - true, !all_nonconst); - } else { - indent(out, 4) << "{\n"; - always_returns = write_function_forset(out, mii->second, min_args, - max_args, expected_params, 6, - coercion_allowed, true, args_type, - return_flags, true, !all_nonconst); - } - - indent(out, 4) << "}\n"; - if (!always_returns) { - indent(out, 4) << "break;\n"; - } - } - - // In NDEBUG case, fall through to the error at end of function. - out << "#ifndef NDEBUG\n"; - - indent(out, 2) << "default:\n"; - - // Format an error saying how many arguments we actually take. So much - // logic for such a silly matter. Sheesh. - ostringstream msg; - msg << methodNameFromCppName(remap, "", false) << "() takes "; - - set::iterator si = num_args.begin(); - msg << *si; - if (num_args.size() == 2) { - msg << " or " << *(++si); - } else if (num_args.size() > 2) { - ++si; - while (si != num_args.end()) { - int num = *si; - if ((++si) == num_args.end()) { - msg << " or " << num; - } else { - msg << ", " << num; - } - } - } - msg << " arguments (%d given)"; - - string count_var = "parameter_count"; - if (add_self) { - count_var += " + 1"; - } - - error_raise_return(out, 4, return_flags, "TypeError", - msg.str(), count_var); - out << "#endif\n"; - indent(out, 2) << "}\n"; - - error_bad_args_return(out, 2, return_flags, expected_params); - - } else { - mii = map_sets.begin(); - - // If no parameters are accepted, we do need to check that the argument - // count is indeed 0, since we won't check that in - // write_function_instance. - if (mii->first == 0 && args_type != AT_no_args) { - switch (args_type) { - case AT_keyword_args: - out << " if (!Dtool_CheckNoArgs(args, kwds)) {\n"; - out << " int parameter_count = (int)PyTuple_Size(args);\n"; - out << " if (kwds != nullptr) {\n"; - out << " parameter_count += (int)PyDict_Size(kwds);\n"; - out << " }\n"; - break; - case AT_varargs: - out << " if (!Dtool_CheckNoArgs(args)) {\n"; - out << " const int parameter_count = (int)PyTuple_GET_SIZE(args);\n"; - break; - case AT_single_arg: - // Shouldn't happen, but let's handle this case nonetheless. - out << " {\n"; - out << " const int parameter_count = 1;\n"; - break; - case AT_no_args: - break; - case AT_unknown: - break; - } - - out << "#ifdef NDEBUG\n"; - error_raise_return(out, 4, return_flags, "TypeError", "function takes no arguments"); - out << "#else\n"; - error_raise_return(out, 4, return_flags, "TypeError", - methodNameFromCppName(remap, "", false) + "() takes no arguments (%d given)", - "parameter_count"); - out << "#endif\n"; - out << " }\n"; - - } else if (args_type == AT_keyword_args && max_required_args == 1 && mii->first == 1) { - // Check this to be sure, as we handle the case of only 1 keyword arg in - // write_function_forset (not using ParseTupleAndKeywords). - out << " int parameter_count = (int)PyTuple_Size(args);\n" - " if (kwds != nullptr) {\n" - " parameter_count += (int)PyDict_Size(kwds);\n" - " }\n" - " if (parameter_count != 1) {\n" - "#ifdef NDEBUG\n"; - error_raise_return(out, 4, return_flags, "TypeError", - "function takes exactly 1 argument"); - out << "#else\n"; - error_raise_return(out, 4, return_flags, "TypeError", - methodNameFromCppName(remap, "", false) + "() takes exactly 1 argument (%d given)", - "parameter_count"); - out << "#endif\n"; - out << " }\n"; - } - - int min_args = min(max_required_args, mii->first); - if (!write_function_forset(out, mii->second, min_args, mii->first, - expected_params, 2, coercion_allowed, true, - args_type, return_flags, true, !all_nonconst)) { - error_bad_args_return(out, 2, return_flags, expected_params); - } - } - - out << "}\n\n"; -} - -/** - * Writes the definition for a coerce constructor: a special constructor that - * is called to implicitly cast a tuple or other type to a desired type. This - * is done by calling the appropriate constructor or static make() function. - * Constructors marked with the "explicit" keyword aren't considered, just - * like in C++. - * - * There are usually two coerce constructors: one for const pointers, one for - * non-const pointers. This is due to the possibility that a static make() - * function may return a const pointer. - * - * There are two variants of this: if the class in question is a - * ReferenceCount, the coerce constructor takes a reference to a PointerTo or - * ConstPointerTo to store the converted pointer in. Otherwise, it is a - * regular pointer, and an additional boolean indicates whether the caller is - * supposed to call "delete" on the coerced pointer or not. - * - * In all cases, the coerce constructor returns a bool indicating whether the - * conversion was possible. It does not raise exceptions when none of the - * constructors matched, but just returns false. - */ -void InterfaceMakerPythonNative:: -write_coerce_constructor(ostream &out, Object *obj, bool is_const) { - std::map > map_sets; - std::map >::iterator mii; - - int max_required_args = 0; - - // Go through the methods and find appropriate static make() functions. - for (Function *func : obj->_methods) { - for (FunctionRemap *remap : func->_remaps) { - if (is_remap_legal(remap) && remap->_flags & FunctionRemap::F_coerce_constructor) { - nassertd(!remap->_has_this) continue; - - // It's a static make() function. - CPPType *return_type = remap->_return_type->get_new_type(); - - if (!is_const && TypeManager::is_const_pointer_or_ref(return_type)) { - // If we're making the non-const coerce constructor, reject this - // remap if it returns a const pointer. - continue; - } - - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - - // Coerce constructor should take at least one argument. - nassertd(max_num_args > 0) continue; - min_num_args = max(min_num_args, 1); - - max_required_args = max(max_num_args, max_required_args); - - for (int i = min_num_args; i <= max_num_args; ++i) { - map_sets[i].insert(remap); - } - - size_t parameter_size = remap->_parameters.size(); - map_sets[parameter_size].insert(remap); - } - } - } - - // Now go through the constructors that are suitable for coercion. This - // excludes copy constructors and ones marked "explicit". - for (Function *func : obj->_constructors) { - for (FunctionRemap *remap : func->_remaps) { - if (is_remap_legal(remap) && remap->_flags & FunctionRemap::F_coerce_constructor) { - nassertd(!remap->_has_this) continue; - - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - - // Coerce constructor should take at least one argument. - nassertd(max_num_args > 0) continue; - min_num_args = max(min_num_args, 1); - - max_required_args = max(max_num_args, max_required_args); - - for (int i = min_num_args; i <= max_num_args; ++i) { - map_sets[i].insert(remap); - } - - size_t parameter_size = remap->_parameters.size(); - map_sets[parameter_size].insert(remap); - } - } - } - - std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - std::string cClassName = obj->_itype.get_true_name(); - - int return_flags = RF_coerced; - - if (TypeManager::is_reference_count(obj->_itype._cpptype)) { - // The coercion works slightly different for reference counted types, - // since we can handle those a bit more nicely by taking advantage of the - // refcount instead of having to use a boolean to indicate that it should - // be managed. - if (is_const) { - out << "bool Dtool_ConstCoerce_" << ClassName << "(PyObject *args, CPT(" << cClassName << ") &coerced) {\n"; - } else { - out << "bool Dtool_Coerce_" << ClassName << "(PyObject *args, PT(" << cClassName << ") &coerced) {\n"; - } - - // Note: this relies on the PT() being initialized to NULL. This is - // currently the case in all invocations, but this may not be true in the - // future. - out << " if (DtoolInstance_GetPointer(args, coerced.cheat(), Dtool_" << ClassName << ")) {\n"; - out << " // The argument is already of matching type, no need to coerce.\n"; - if (!is_const) { - out << " if (!DtoolInstance_IS_CONST(args)) {\n"; - out << " // A non-const instance is required, which this is.\n"; - out << " coerced->ref();\n"; - out << " return true;\n"; - out << " }\n"; - } else { - out << " coerced->ref();\n"; - out << " return true;\n"; - } - return_flags |= RF_err_false; - - } else { - out << cClassName << " *Dtool_Coerce_" << ClassName << "(PyObject *args, " << cClassName << " &coerced) {\n"; - - out << " " << cClassName << " *local_this;\n"; - out << " if (DtoolInstance_GetPointer(args, local_this, Dtool_" << ClassName << ")) {\n"; - out << " if (DtoolInstance_IS_CONST(args)) {\n"; - out << " // This is a const object. Make a copy.\n"; - out << " coerced = *(const " << cClassName << " *)local_this;\n"; - out << " return &coerced;\n"; - out << " }\n"; - out << " return local_this;\n"; - - return_flags |= RF_err_null; - } - - out << " }\n\n"; - - if (map_sets.empty()) { - error_return(out, 2, return_flags); - out << "}\n\n"; - return; - } - - // Coercion constructors are special cases in that they can take either a - // single value or a tuple. (They never, however, take a tuple containing a - // single value.) - string expected_params; - mii = map_sets.find(1); - if (mii != map_sets.end()) { - out << " if (!PyTuple_Check(args)) {\n"; - out << " PyObject *arg = args;\n"; - - write_function_forset(out, mii->second, mii->first, mii->first, expected_params, 4, false, false, - AT_single_arg, return_flags, true, false); - - if (map_sets.size() == 1) { - out << " }\n"; - // out << " PyErr_Clear();\n"; - error_return(out, 2, return_flags); - out << "}\n\n"; - return; - } - - // We take this one out of the map sets. There's not much value in - // coercing tuples containing just one value. - map_sets.erase(mii); - - out << " } else {\n"; - } else { - out << " if (PyTuple_Check(args)) {\n"; - } - - max_required_args = collapse_default_remaps(map_sets, max_required_args); - - if (map_sets.size() > 1) { - indent(out, 4) << "switch (PyTuple_GET_SIZE(args)) {\n"; - - for (mii = map_sets.begin(); mii != map_sets.end(); ++mii) { - int max_args = mii->first; - int min_args = min(max_required_args, max_args); - - // This is not called for tuples containing just one value or no values - // at all, so we should never have to consider that case. - if (min_args < 2) { - min_args = 2; - } - nassertd(max_args >= min_args) continue; - - for (int i = min_args; i < max_args; ++i) { - if (i != 1) { - indent(out, 6) << "case " << i << ":\n"; - } - } - indent(out, 6) << "case " << max_args << ": {\n"; - - if (!write_function_forset(out, mii->second, min_args, max_args, - expected_params, 8, false, false, - AT_varargs, return_flags, true, false)) { - indent(out, 8) << "break;\n"; - } - indent(out, 6) << "}\n"; - } - indent(out, 4) << "}\n"; - - } else { - mii = map_sets.begin(); - - int max_args = mii->first; - int min_args = min(max_required_args, max_args); - - // This is not called for tuples containing just one value or no values at - // all, so we should never have to consider that case. - if (min_args < 2) { - min_args = 2; - } - nassertv(max_args >= min_args); - - if (min_args == max_args) { - indent(out, 4) << "if (PyTuple_GET_SIZE(args) == " << mii->first << ") {\n"; - } else { - indent(out, 4) << "Py_ssize_t size = PyTuple_GET_SIZE(args);\n"; - // Not sure if this check really does any good. I guess it's a useful - // early-fail test. - indent(out, 4) << "if (size >= " << min_args << " && size <= " << max_args << ") {\n"; - } - - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, false, false, - AT_varargs, return_flags, true, false); - indent(out, 4) << "}\n"; - } - - out << " }\n\n"; - // out << " PyErr_Clear();\n"; - error_return(out, 2, return_flags); - out << "}\n\n"; -} - -/** - * Special case optimization: if the last map is a subset of the map before - * it, we can merge the cases. When this happens, we can make use of a - * special feature of PyArg_ParseTuple for handling of these last few default - * arguments. - * - * This isn't just to help reduce the amount of generated code; it also - * enables arbitrary selection of keyword arguments for many functions, ie. - * for this function: - * - * int func(int a=0, int b=0, bool c=false, string d=""); - * - * Thanks to this mechanism, we can call it like so: - * - * func(c=True, d=".") - */ -int InterfaceMakerPythonNative:: -collapse_default_remaps(std::map > &map_sets, - int max_required_args) { - if (map_sets.size() < 1) { - return max_required_args; - } - - std::map >::reverse_iterator rmi, rmi_next; - rmi = map_sets.rbegin(); - rmi_next = rmi; - for (++rmi_next; rmi_next != map_sets.rend();) { - if (std::includes(rmi_next->second.begin(), rmi_next->second.end(), - rmi->second.begin(), rmi->second.end())) { - - // rmi_next has a superset of the remaps in rmi, and we are going to - // erase rmi_next, so put all the remaps in rmi. - - max_required_args = rmi_next->first; - rmi = rmi_next; - ++rmi_next; - } else { - break; - } - } - - // Now erase the other remap sets. Reverse iterators are weird, we first - // need to get forward iterators and decrement them by one. - std::map >::iterator erase_begin, erase_end; - erase_begin = rmi.base(); - erase_end = map_sets.rbegin().base(); - --erase_begin; - --erase_end; - - if (erase_begin == erase_end) { - return max_required_args; - } - - // We're never erasing the map set with the highest number of args. - nassertr(erase_end != map_sets.end(), max_required_args); - - // We know erase_begin is a superset of erase_end, but we want all the - // remaps in erase_end (which we aren't erasing). if (rmi == - // map_sets.rbegin()) { - erase_end->second = erase_begin->second; - // } - - map_sets.erase(erase_begin, erase_end); - - assert(map_sets.size() >= 1); - - return max_required_args; -} - -/** - - */ -int get_type_sort(CPPType *type) { - int answer = 0; -// printf(" %s\n",type->get_local_name().c_str()); - - // The highest numbered one will be checked first. - if (TypeManager::is_nullptr(type)) { - return 15; - } else if (TypeManager::is_pointer_to_Py_buffer(type)) { - return 14; - } else if (TypeManager::is_pointer_to_PyTypeObject(type)) { - return 13; - } else if (TypeManager::is_pointer_to_PyObject(type)) { - return 12; - } else if (TypeManager::is_wstring(type)) { - return 11; - } else if (TypeManager::is_wchar_pointer(type)) { - return 10; - } else if (TypeManager::is_string(type)) { - return 9; - } else if (TypeManager::is_char_pointer(type)) { - return 8; - } else if (TypeManager::is_unsigned_longlong(type)) { - return 7; - } else if (TypeManager::is_longlong(type)) { - return 6; - } else if (TypeManager::is_integer(type) && !TypeManager::is_bool(type)) { - return 5; - } else if (TypeManager::is_double(type)) { - return 4; - } else if (TypeManager::is_float(type)) { - return 3; - } else if (TypeManager::is_pointer_to_simple(type)) { - return 2; - } else if (TypeManager::is_bool(type)) { - return 1; - } else if (TypeManager::is_pointer(type) || - TypeManager::is_reference(type) || - TypeManager::is_struct(type)) { - answer = 20; - int deepest = 0; - - // Sort such that more derived classes come first. - type = TypeManager::unwrap(TypeManager::resolve_type(type)); - if (type != nullptr) { - CPPStructType *struct_type = type->as_struct_type(); - if (struct_type != nullptr) { - for (const CPPStructType::Base &base : struct_type->_derivation) { - if (base._base != nullptr) { - int this_one = get_type_sort(base._base); - if (this_one > deepest) { - deepest = this_one; - } - } - } - } - } - answer += deepest; -// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); - } - -// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer); - return answer; -} - -// The Core sort function for remap calling orders.. -bool RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { - assert(in1 != nullptr); - assert(in2 != nullptr); - - if (in1->_const_method != in2->_const_method) { - // Non-const methods should come first. - return in2->_const_method; - } - - if (in1->_parameters.size() != in2->_parameters.size()) { - return (in1->_parameters.size() > in2->_parameters.size()); - } - - int pcount = in1->_parameters.size(); - for (int x = 0; x < pcount; x++) { - CPPType *orig_type1 = in1->_parameters[x]._remap->get_orig_type(); - CPPType *orig_type2 = in2->_parameters[x]._remap->get_orig_type(); - - int pd1 = get_type_sort(orig_type1); - int pd2 = get_type_sort(orig_type2); - if (pd1 != pd2) { - return (pd1 > pd2); - } - } - - // ok maybe something to do with return strength.. - - return false; -} - -/** - * Writes out a set of function wrappers that handle all instances of a - * particular function with the same number of parameters. (Actually, in some - * cases relating to default argument handling, this may be called with remaps - * taking a range of parameters.) - * - * min_num_args and max_num_args are the range of parameter counts to respect - * for these functions. This is important for default argument handling. - * - * expected_params is a reference to a string that will be filled in with a - * list of overloads that this function takes, for displaying in the doc - * string and error messages. - * - * If coercion_allowed is true, it will attempt to convert arguments to the - * appropriate parameter type using the appropriate Dtool_Coerce function. - * This means it may write some remaps twice: once without coercion, and then - * it may go back and write it a second time to try parameter coercion. - * - * If report_errors is true, it will print an error and exit when one has - * occurred, instead of falling back to the next overload. This is - * automatically disabled when more than one function is passed. - * - * args_type indicates whether this function takes no args, a single PyObject* - * arg, an args tuple, or an args tuple and kwargs dictionary. - * - * return_flags indicates which value should be returned from the wrapper - * function and what should be returned on error. - * - * If check_exceptions is false, it will not check if the function raised an - * exception, except if it took PyObject* arguments. This should NEVER be - * false for C++ functions that call Python code, since that would block a - * meaningful exception like SystemExit or KeyboardInterrupt. - * - * If verify_const is set, it will write out a check to make sure that non- - * const functions aren't called for a const "this". This is usually only - * false when write_function_for_name has already done this check (which it - * does when *all* remaps are non-const). - * - * If first_pexpr is not empty, it represents the preconverted value of the - * first parameter. This is a special-case hack for one of the slot - * functions. - */ -bool InterfaceMakerPythonNative:: -write_function_forset(ostream &out, - const std::set &remapsin, - int min_num_args, int max_num_args, - string &expected_params, int indent_level, - bool coercion_allowed, bool report_errors, - ArgsType args_type, int return_flags, - bool check_exceptions, bool verify_const, - const string &first_pexpr) { - - if (remapsin.empty()) { - return false; - } - - FunctionRemap *remap = nullptr; - std::set::iterator sii; - - bool all_nonconst = false; - bool always_returns = true; - - if (verify_const) { - // Check if all of the remaps are non-const. If so, we only have to check - // the constness of the self pointer once, rather than per remap. - all_nonconst = true; - - for (sii = remapsin.begin(); sii != remapsin.end(); ++sii) { - remap = (*sii); - if (!remap->_has_this || remap->_const_method) { - all_nonconst = false; - break; - } - } - - if (all_nonconst) { - // Yes, they do. Check that the parameter has the required constness. - indent(out, indent_level) - << "if (!DtoolInstance_IS_CONST(self)) {\n"; - indent_level += 2; - verify_const = false; - } - } - - string first_param_name; - bool same_first_param = false; - - // If there's only one arg and all remaps have the same parameter name, we - // extract it from the dictionary, so we don't have to call - // ParseTupleAndKeywords. - if (first_pexpr.empty() && min_num_args == 1 && max_num_args == 1 && - args_type == AT_keyword_args) { - sii = remapsin.begin(); - remap = (*sii); - if (remap->_parameters[(int)remap->_has_this]._has_name) { - first_param_name = remap->_parameters[(int)remap->_has_this]._name; - same_first_param = true; - - for (++sii; sii != remapsin.end(); ++sii) { - remap = (*sii); - if (remap->_parameters[(int)remap->_has_this]._name != first_param_name) { - same_first_param = false; - break; - } - } - } - } - - if (same_first_param) { - // Yes, they all have the same argument name (or there is only one remap). - // Extract it from the dict so we don't have to call - // ParseTupleAndKeywords. - indent(out, indent_level) << "PyObject *arg;\n"; - indent(out, indent_level) << "if (Dtool_ExtractArg(&arg, args, kwds, \"" << first_param_name << "\")) {\n"; - indent_level += 2; - args_type = AT_single_arg; - always_returns = false; - } - - if (remapsin.size() > 1) { - // There are multiple different overloads for this number of parameters. - // Sort them all into order from most-specific to least-specific, then try - // them one at a time. - std::vector remaps (remapsin.begin(), remapsin.end()); - std::sort(remaps.begin(), remaps.end(), RemapCompareLess); - std::vector::const_iterator sii; - - int num_coercion_possible = 0; - bool caught_all = false; - sii = remaps.begin(); - while (sii != remaps.end()) { - remap = *(sii++); - - if (coercion_allowed && is_remap_coercion_possible(remap)) { - if (++num_coercion_possible == 1 && sii == remaps.end()) { - // This is the last remap, and it happens to be the only one with - // coercion possible. So we might as well just break off now, and - // let this case be handled by the coercion loop, below. BUG: this - // remap doesn't get listed in expected_params. - break; - } - } - - if (caught_all) { - indent(out, indent_level) - << " // [DCE] -2 \n"; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - continue; - } - - bool remap_verify_const = verify_const && (remap->_has_this && !remap->_const_method); - if (remap_verify_const) { - // If it's a non-const method, we only allow a non-const this. - indent(out, indent_level) - << "if (!DtoolInstance_IS_CONST(self)) {\n"; - } else { - indent(out, indent_level) - << "{\n"; - } - - indent(out, indent_level) << " // -2 "; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - - // NB. We don't pass on report_errors here because we want it to - // silently drop down to the next overload. - - if (write_function_instance(out, remap, min_num_args, max_num_args, - expected_params, indent_level + 2, - false, false, args_type, return_flags, - check_exceptions, first_pexpr)) { - // The rest of the overloads are dead code. - if (!remap_verify_const) { - caught_all = true; - //indent(out, indent_level) << " // caught all cases here\n"; - } - } - - indent(out, indent_level) << "}\n\n"; - } - - // Go through one more time, but allow coercion this time. - if (coercion_allowed && !caught_all) { - for (sii = remaps.begin(); sii != remaps.end(); ++sii) { - remap = (*sii); - if (!is_remap_coercion_possible(remap)) { - indent(out, indent_level) - << "// No coercion possible: "; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - continue; - } - - if (caught_all) { - indent(out, indent_level) - << " // [DCE] -2 \n"; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - continue; - } - - bool remap_verify_const = verify_const && (remap->_has_this && !remap->_const_method); - if (remap_verify_const) { - indent(out, indent_level) - << "if (!DtoolInstance_IS_CONST(self)) {\n"; - } else { - indent(out, indent_level) - << "{\n"; - } - - indent(out, indent_level) << " // -2 "; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - - string ignore_expected_params; - if (write_function_instance(out, remap, min_num_args, max_num_args, - ignore_expected_params, indent_level + 2, - true, false, args_type, return_flags, - check_exceptions, first_pexpr)) { - // The rest of the overloads are dead code. - if (!remap_verify_const) { - caught_all = true; - //indent(out, indent_level) << " // caught all cases here\n"; - } - } - - indent(out, indent_level) << "}\n\n"; - } - } - - if (!caught_all) { - always_returns = false; - } - } else { - // There is only one possible overload with this number of parameters. - // Just call it. - sii = remapsin.begin(); - - remap = (*sii); - indent(out, indent_level) - << "// 1-" ; - remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); - out << "\n"; - - if (!write_function_instance(out, remap, min_num_args, max_num_args, - expected_params, indent_level, - coercion_allowed, report_errors, - args_type, return_flags, - check_exceptions, first_pexpr)) { - always_returns = false; - } - } - - // Close the brace we opened earlier. - if (same_first_param) { - indent_level -= 2; - indent(out, indent_level) << "}\n"; - } - - // If we did a const check earlier, and we were asked to report errors, - // write out an else case raising an exception. - if (all_nonconst) { - if (report_errors) { - indent(out, indent_level - 2) - << "} else {\n"; - - string class_name = remap->_cpptype->get_simple_name(); - ostringstream msg; - msg << "Cannot call " - << classNameFromCppName(class_name, false) - << "." << methodNameFromCppName(remap, class_name, false) - << "() on a const object."; - - out << "#ifdef NDEBUG\n"; - error_raise_return(out, indent_level, return_flags, "TypeError", - "non-const method called on const object"); - out << "#else\n"; - error_raise_return(out, indent_level, return_flags, "TypeError", msg.str()); - out << "#endif\n"; - } else { - always_returns = false; - } - indent_level -= 2; - indent(out, indent_level) << "}\n"; - } - - return always_returns; -} - -/** - * Writes out the code to handle a a single instance of an overloaded - * function. This will convert all of the arguments from PyObject* to the - * appropriate C++ type, call the C++ function, possibly check for errors, and - * construct a Python wrapper for the return value. - * - * return_flags indicates which value should be returned from the wrapper - * function and what should be returned on error. - * - * If coercion_possible is true, it will attempt to convert arguments to the - * appropriate parameter type using the appropriate Dtool_Coerce function. - * - * If report_errors is true, it will print an error and exit when one has - * occurred, instead of falling back to the next overload. This should be - * done if it is the only overload. - * - * If check_exceptions is false, it will not check if the function raised an - * exception, except if it took PyObject* arguments. This should NEVER be - * false for C++ functions that call Python code, since that would block a - * meaningful exception like SystemExit or KeyboardInterrupt. - * - * If first_pexpr is not empty, it represents the preconverted value of the - * first parameter. This is a special-case hack for one of the slot - * functions. - * - * Returns true if the function returns unconditionally, false if it may fall - * through and additional error handling code is needed. - */ -bool InterfaceMakerPythonNative:: -write_function_instance(ostream &out, FunctionRemap *remap, - int min_num_args, int max_num_args, - string &expected_params, int indent_level, - bool coercion_possible, bool report_errors, - ArgsType args_type, int return_flags, - bool check_exceptions, - const string &first_pexpr) { - string format_specifiers; - string keyword_list_old; - string keyword_list_new; - string parameter_list; - string container; - string type_check; - string param_name; - bool has_keywords = false; - vector_string pexprs; - LineStream extra_convert; - ostringstream extra_param_check; - LineStream extra_cleanup; - int min_version = 0; - - // This will be set if the function itself is suspected of possibly raising - // a TypeError. - bool may_raise_typeerror = false; - - // This will be set to true if one of the things we're about to do *might* - // raise a TypeError that we may have to clear. - bool clear_error = false; - - bool is_constructor = (remap->_type == FunctionRemap::T_constructor); - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - // Make one pass through the parameter list. We will output a one-line - // temporary variable definition for each parameter, while simultaneously - // building the ParseTuple() function call and also the parameter expression - // list for call_function(). - - expected_params += methodNameFromCppName(remap, "", false); - expected_params += "("; - - int num_params = 0; - - if ((remap->_flags & FunctionRemap::F_explicit_args) == 0) { - num_params = max_num_args; - if (remap->_has_this) { - num_params += 1; - } - if (num_params > (int)remap->_parameters.size()) { - // Limit to how many parameters this remap actually has. - num_params = (int)remap->_parameters.size(); - max_num_args = num_params; - if (remap->_has_this) { - --max_num_args; - } - } - nassertr(num_params <= (int)remap->_parameters.size(), false); - } - - bool only_pyobjects = true; - - int pn = 0; - - if (remap->_has_this) { - // The first parameter is the 'this' parameter. - string expected_class_name = classNameFromCppName(remap->_cpptype->get_simple_name(), false); - if (remap->_const_method) { - expected_params += expected_class_name + " self"; - string class_name = remap->_cpptype->get_local_name(&parser); - container = "(const " + class_name + "*)local_this"; - } else { - expected_params += "const " + expected_class_name + " self"; - container = "local_this"; - } - pexprs.push_back(container); - ++pn; - } - - if (!first_pexpr.empty()) { - if (pn >= num_params) { - // first_pexpr was passed even though the function takes no arguments. - nassert_raise("pn < num_params"); - } else { - // The first actual argument was already converted. - if (pn > 0) { - expected_params += ", "; - } - expected_params += first_pexpr; - pexprs.push_back(first_pexpr); - ++pn; - } - } - - if (remap->_flags & FunctionRemap::F_explicit_args) { - // The function handles the arguments by itself. - expected_params += "*args"; - pexprs.push_back("args"); - if (remap->_args_type == AT_keyword_args) { - if (args_type == AT_keyword_args) { - expected_params += ", **kwargs"; - pexprs.push_back("kwds"); - } else { - pexprs.push_back("nullptr"); - } - } - num_params = 0; - } - - // Now convert (the rest of the) actual arguments, one by one. - for (; pn < num_params; ++pn) { - ParameterRemap *param = remap->_parameters[pn]._remap; - CPPType *orig_type = param->get_orig_type(); - CPPType *type = param->get_new_type(); - CPPExpression *default_value = param->get_default_value(); - param_name = remap->get_parameter_name(pn); - - if (!is_cpp_type_legal(orig_type)) { - // We can't wrap this. We sometimes get here for default arguments. - // Just skip this parameter. - continue; - } - - // Has this remap been selected to consider optional arguments for this - // parameter? We can do that by adding a vertical bar to the - // PyArg_ParseTuple format string, coupled with some extra logic in the - // argument handling, below. - bool is_optional = false; - if (remap->_has_this && !is_constructor) { - if (pn > min_num_args) { - is_optional = true; - if ((pn - 1) == min_num_args) { - format_specifiers += "|"; - } - } - } else { - if (pn >= min_num_args) { - is_optional = true; - if (pn == min_num_args) { - format_specifiers += "|"; - } - } - } - - if (pn > 0) { - expected_params += ", "; - } - - // This is the string to convert our local variable to the appropriate C++ - // type. Normally this is just a cast. - string pexpr_string = - "(" + orig_type->get_local_name(&parser) + ")" + param_name; - - string default_expr; - const char *null_assign = ""; - - if (is_optional) { - // If this is an optional argument, PyArg_ParseTuple will leave the - // variable unchanged if it has been omitted, so we have to initialize - // it to the desired default expression. Format it. - ostringstream default_expr_str; - default_expr_str << " = "; - default_value->output(default_expr_str, 0, &parser, false); - default_expr = default_expr_str.str(); - null_assign = " = nullptr"; - - // We should only ever have to consider optional arguments for functions - // taking a variable number of arguments. - nassertr(args_type == AT_varargs || args_type == AT_keyword_args, false); - } - - string reported_name = remap->_parameters[pn]._name; - if (!keyword_list_old.empty()) { - keyword_list_old += ", "; - keyword_list_new += ", "; - } - if (remap->_parameters[pn]._has_name) { - has_keywords = true; - } - keyword_list_old += "\"" + reported_name + "\""; - if (has_keywords) { - keyword_list_new += "\"" + reported_name + "\""; - } else { - // Positional-only argument. - keyword_list_new += "\"\""; - } - - if (param->new_type_is_atomic_string()) { - - if (TypeManager::is_char_pointer(orig_type)) { - indent(out, indent_level) << "char "; - if (TypeManager::is_const_char_pointer(orig_type)) { - out << "const "; - } - out << "*" << param_name << default_expr << ";\n"; - format_specifiers += "z"; - parameter_list += ", &" + param_name; - expected_params += "str"; - - } else if (TypeManager::is_wchar_pointer(orig_type)) { - out << "#if PY_VERSION_HEX >= 0x03020000\n"; - indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n"; - out << "#else\n"; - indent(out, indent_level) << "PyUnicodeObject *" << param_name << null_assign << ";\n"; - out << "#endif\n"; - format_specifiers += "U"; - parameter_list += ", &" + param_name; - - if (is_optional) { - extra_convert - << "wchar_t *" << param_name << "_str = nullptr;\n" - << "if (" << param_name << " != nullptr) {\n" - << "#if PY_VERSION_HEX >= 0x03030000\n" - << " " << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n" - << "#else" - << "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n" - << " " << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n" - << "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n" - << param_name << "_str[" << param_name << "_len] = 0;\n" - << "#endif\n" - << "} else {\n" - << " " << param_name << "_str" << default_expr << ";\n" - << "}\n"; - } else { - extra_convert - << "#if PY_VERSION_HEX >= 0x03030000\n" - << "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n" - << "#else" - << "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n" - << "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n" - << "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n" - << param_name << "_str[" << param_name << "_len] = 0;\n" - << "#endif\n"; - } - - pexpr_string = param_name + "_str"; - - extra_cleanup - << "#if PY_VERSION_HEX >= 0x03030000\n" - << "PyMem_Free(" << param_name << "_str);\n" - << "#endif\n"; - - expected_params += "unicode"; - - } else if (TypeManager::is_wstring(orig_type) || - TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) { - out << "#if PY_VERSION_HEX >= 0x03020000\n"; - indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n"; - out << "#else\n"; - indent(out, indent_level) << "PyUnicodeObject *" << param_name << null_assign << ";\n"; - out << "#endif\n"; - format_specifiers += "U"; - parameter_list += ", &" + param_name; - - if (is_optional) { - extra_convert - << "Py_ssize_t " << param_name << "_len;\n" - << "wchar_t *" << param_name << "_str = nullptr;\n" - << "std::wstring " << param_name << "_wstr;\n" - << "if (" << param_name << " != nullptr) {\n" - << "#if PY_VERSION_HEX >= 0x03030000\n" - << " " << param_name << "_str = PyUnicode_AsWideCharString(" - << param_name << ", &" << param_name << "_len);\n" - << "#else\n" - << " " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n" - << " " << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n" - << "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n" - << "#endif\n" - << " " << param_name << "_wstr.assign(" << param_name << "_str, " << param_name << "_len);\n" - << "} else {\n" - << " " << param_name << "_wstr" << default_expr << ";\n" - << "}\n"; - pexpr_string = "std::move(" + param_name + "_wstr)"; - } else { - extra_convert - << "#if PY_VERSION_HEX >= 0x03030000\n" - << "Py_ssize_t " << param_name << "_len;\n" - << "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString(" - << param_name << ", &" << param_name << "_len);\n" - << "#else\n" - << "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n" - << "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n" - << "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n" - << "#endif\n"; - pexpr_string = param_name + "_str, " + param_name + "_len"; - } - - extra_cleanup - << "#if PY_VERSION_HEX >= 0x03030000\n" - << "PyMem_Free(" << param_name << "_str);\n" - << "#endif\n"; - - expected_params += "unicode"; - - } else { // A regular string. - if (is_optional) { - CPPExpression::Type expr_type = default_value->_type; - if (expr_type == CPPExpression::T_default_construct) { - // The default string constructor yields an empty string. - indent(out, indent_level) << "const char *" << param_name << "_str = \"\";\n"; - indent(out, indent_level) << "Py_ssize_t " << param_name << "_len = 0;\n"; - } else { - // We only get here for string literals, so this should be fine - indent(out, indent_level) << "const char *" << param_name << "_str" - << default_expr << ";\n"; - indent(out, indent_level) << "Py_ssize_t " << param_name << "_len = " - << default_value->_str.size() << ";\n"; - } - } else { - indent(out, indent_level) << "const char *" << param_name << "_str = nullptr;\n"; - indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n"; - } - - if (args_type == AT_single_arg) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &" - << param_name << "_len);\n"; - out << "#else\n"; // NB. PyString_AsStringAndSize also accepts a PyUnicode. - indent(out, indent_level) << "if (PyString_AsStringAndSize(arg, (char **)&" - << param_name << "_str, &" << param_name << "_len) == -1) {\n"; - indent(out, indent_level + 2) << param_name << "_str = nullptr;\n"; - indent(out, indent_level) << "}\n"; - out << "#endif\n"; - - extra_param_check << " && " << param_name << "_str != nullptr"; - } else { - format_specifiers += "s#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - } - - //if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { - // pexpr_string = "&std::string(" + param_name + "_str, " + param_name + "_len)"; - //} else { - pexpr_string = param_name + "_str, " + param_name + "_len"; - //} - expected_params += "str"; - } - // Remember to clear the TypeError that any of the above methods raise. - clear_error = true; - only_pyobjects = false; - - } else if (TypeManager::is_vector_unsigned_char(type)) { - indent(out, indent_level) << "unsigned char *" << param_name << "_str = nullptr;\n"; - indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n"; - - if (args_type == AT_single_arg) { - extra_param_check << " && PyBytes_AsStringAndSize(arg, (char **)&" - << param_name << "_str, &" << param_name << "_len) >= 0"; - } else { - format_specifiers += "\" FMTCHAR_BYTES \"#"; - parameter_list += ", &" + param_name + "_str, &" + param_name + "_len"; - } - - pexpr_string = type->get_local_name(&parser); - pexpr_string += "(" + param_name + "_str, " + param_name + "_str + " + param_name + "_len" + ")"; - expected_params += "bytes"; - - // Remember to clear the TypeError that any of the above methods raise. - clear_error = true; - only_pyobjects = false; - - } else if (TypeManager::is_scoped_enum(type)) { - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name; - if (default_value != nullptr) { - out << " = nullptr"; - } - out << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - - CPPEnumType *enum_type = (CPPEnumType *)TypeManager::unwrap(type); - //CPPType *underlying_type = enum_type->get_underlying_type(); - //underlying_type = TypeManager::unwrap_const(underlying_type); - //indent(out, indent_level); - //underlying_type->output_instance(out, param_name + "_val", &parser); - //out << default_expr << ";\n"; - extra_convert << "long " << param_name << "_val"; - - if (default_value != nullptr) { - extra_convert << " = (long)"; - default_value->output(extra_convert, 0, &parser, false); - extra_convert << - ";\nif (" << param_name << " != nullptr) {\n" - " " << param_name << "_val = Dtool_EnumValue_AsLong(" + param_name + ");\n" - "}"; - } else { - extra_convert - << ";\n" - << param_name << "_val = Dtool_EnumValue_AsLong(" + param_name + ");\n"; - } - - pexpr_string = "(" + enum_type->get_local_name(&parser) + ")" + param_name + "_val"; - expected_params += classNameFromCppName(enum_type->get_simple_name(), false); - extra_param_check << " && " << param_name << "_val != -1"; - clear_error = true; - - } else if (TypeManager::is_bool(type)) { - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name; - if (is_optional) { - CPPExpression::Result res = default_value->evaluate(); - if (res._type != CPPExpression::RT_error) { - // It's a compile-time constant. Write Py_True or Py_False. - out << " = " << (res.as_boolean() ? "Py_True" : "Py_False"); - } else { - // Select Py_True or Py_False at runtime. - out << " = ("; - default_value->output(out, 0, &parser, false); - out << ") ? Py_True : Py_False"; - } - } - out << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - pexpr_string = "(PyObject_IsTrue(" + param_name + ") != 0)"; - expected_params += "bool"; - - } else if (TypeManager::is_nullptr(type)) { - if (args_type == AT_single_arg) { - type_check = "arg == Py_None"; - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << default_expr << ";\n"; - extra_param_check << " && " << param_name << " == Py_None"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - pexpr_string = "nullptr"; - expected_params += "NoneType"; - - } else if (TypeManager::is_char(type)) { - indent(out, indent_level) << "char *" << param_name << "_str;\n"; - indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n"; - - format_specifiers += "s#"; - parameter_list += ", &" + param_name + "_str, &" + param_name + "_len"; - extra_param_check << " && " << param_name << "_len == 1"; - - pexpr_string = param_name + "_str[0]"; - expected_params += "char"; - only_pyobjects = false; - - } else if (TypeManager::is_wchar(type)) { - out << "#if PY_VERSION_HEX >= 0x03020000\n"; - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - out << "#else\n"; - indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n"; - out << "#endif\n"; - format_specifiers += "U"; - parameter_list += ", &" + param_name; - - // We tell it to copy 2 characters, but make sure it only copied one, as - // a trick to check for the proper length in one go. - extra_convert << "wchar_t " << param_name << "_chars[2];\n"; - extra_param_check << " && PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_chars, 2) == 1"; - - pexpr_string = param_name + "_chars[0]"; - expected_params += "unicode char"; - only_pyobjects = false; - clear_error = true; - - } else if (TypeManager::is_ssize(type)) { - indent(out, indent_level) << "Py_ssize_t " << param_name << default_expr << ";\n"; - format_specifiers += "n"; - parameter_list += ", &" + param_name; - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_size(type)) { - if (args_type == AT_single_arg) { - type_check = "PyLongOrInt_Check(arg)"; - - extra_convert << - "size_t arg_val = PyLongOrInt_AsSize_t(arg);\n" - "#ifndef NDEBUG\n" - "if (arg_val == (size_t)-1 && PyErr_Occurred()) {\n"; - error_return(extra_convert, 2, return_flags); - extra_convert << - "}\n" - "#endif\n"; - - pexpr_string = "arg_val"; - - } else { - // It certainly isn't the exact same thing as size_t, but Py_ssize_t - // should at least be the same size. The problem with mapping this to - // unsigned int is that that doesn't work well on 64-bit systems, on - // which size_t is a 64-bit integer. - indent(out, indent_level) << "Py_ssize_t " << param_name << default_expr << ";\n"; - format_specifiers += "n"; - parameter_list += ", &" + param_name; - - extra_convert - << "#ifndef NDEBUG\n" - << "if (" << param_name << " < 0) {\n"; - - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "can't convert negative value %zd to size_t", - param_name); - extra_convert - << "}\n" - << "#endif\n"; - } - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_longlong(type)) { - // It's not trivial to do overflow checking for a long long, so we - // simply don't do it. - if (TypeManager::is_unsigned_longlong(type)) { - indent(out, indent_level) << "unsigned PY_LONG_LONG " << param_name << default_expr << ";\n"; - format_specifiers += "K"; - } else { - indent(out, indent_level) << "PY_LONG_LONG " << param_name << default_expr << ";\n"; - format_specifiers += "L"; - } - parameter_list += ", &" + param_name; - expected_params += "long"; - only_pyobjects = false; - - } else if (TypeManager::is_unsigned_short(type) || - TypeManager::is_unsigned_char(type) || TypeManager::is_signed_char(type)) { - - if (args_type == AT_single_arg) { - type_check = "PyLongOrInt_Check(arg)"; - extra_convert - << "long " << param_name << " = PyLongOrInt_AS_LONG(arg);\n"; - - pexpr_string = "(" + type->get_local_name(&parser) + ")" + param_name; - } else { - indent(out, indent_level) << "long " << param_name << default_expr << ";\n"; - format_specifiers += "l"; - parameter_list += ", &" + param_name; - } - - // The "H" format code, unlike "h", does not do overflow checking, so we - // have to do it ourselves (except in release builds). - extra_convert - << "#ifndef NDEBUG\n"; - - if (TypeManager::is_unsigned_short(type)) { - extra_convert << "if (" << param_name << " < 0 || " << param_name << " > USHRT_MAX) {\n"; - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "value %ld out of range for unsigned short integer", - param_name); - } else if (TypeManager::is_unsigned_char(type)) { - extra_convert << "if (" << param_name << " < 0 || " << param_name << " > UCHAR_MAX) {\n"; - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "value %ld out of range for unsigned byte", - param_name); - } else { - extra_convert << "if (" << param_name << " < SCHAR_MIN || " << param_name << " > SCHAR_MAX) {\n"; - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "value %ld out of range for signed byte", - param_name); - } - - extra_convert - << "}\n" - << "#endif\n"; - - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_short(type)) { - if (args_type == AT_single_arg) { - type_check = "PyLongOrInt_Check(arg)"; - - // Perform overflow checking in debug builds. - extra_convert - << "long arg_val = PyLongOrInt_AS_LONG(arg);\n" - << "#ifndef NDEBUG\n" - << "if (arg_val < SHRT_MIN || arg_val > SHRT_MAX) {\n"; - - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "value %ld out of range for signed short integer", - "arg_val"); - extra_convert - << "}\n" - << "#endif\n"; - - pexpr_string = "(" + type->get_local_name(&parser) + ")arg_val"; - - } else { - indent(out, indent_level) << "short " << param_name << default_expr << ";\n"; - format_specifiers += "h"; - parameter_list += ", &" + param_name; - } - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_unsigned_integer(type)) { - if (args_type == AT_single_arg) { - // Windows has 32-bit longs, and Python 2 stores a C long for PyInt - // internally, so a PyInt wouldn't cover the whole range; that's why - // we have to accept PyLong as well here. - type_check = "PyLongOrInt_Check(arg)"; - extra_convert - << "unsigned long " << param_name << " = PyLong_AsUnsignedLong(arg);\n"; - pexpr_string = "(" + type->get_local_name(&parser) + ")" + param_name; - } else { - indent(out, indent_level) << "unsigned long " << param_name << default_expr << ";\n"; - format_specifiers += "k"; - parameter_list += ", &" + param_name; - } - - // The "I" format code, unlike "i", does not do overflow checking, so we - // have to do it ourselves (in debug builds). Note that Python 2 stores - // longs internally, for ints, so we don't do it for Python 2 on - // Windows, where longs are the same size as ints. BUG: does not catch - // negative values on Windows when going through the PyArg_ParseTuple - // case. - if (!TypeManager::is_long(type)) { - extra_convert - << "#if (SIZEOF_LONG > SIZEOF_INT) && !defined(NDEBUG)\n" - << "if (" << param_name << " > UINT_MAX) {\n"; - - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "value %lu out of range for unsigned integer", - param_name); - - extra_convert - << "}\n" - << "#endif\n"; - } - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_long(type)) { - // Signed longs are equivalent to Python's int type. - if (args_type == AT_single_arg) { - pexpr_string = "PyLongOrInt_AS_LONG(arg)"; - type_check = "PyLongOrInt_Check(arg)"; - } else { - indent(out, indent_level) << "long " << param_name << default_expr << ";\n"; - format_specifiers += "l"; - parameter_list += ", &" + param_name; - } - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_integer(type)) { - if (args_type == AT_single_arg) { - type_check = "PyLongOrInt_Check(arg)"; - - // Perform overflow checking in debug builds. Note that Python 2 - // stores longs internally, for ints, so we don't do it on Windows, - // where longs are the same size as ints. - extra_convert - << "long arg_val = PyLongOrInt_AS_LONG(arg);\n" - << "#if (SIZEOF_LONG > SIZEOF_INT) && !defined(NDEBUG)\n" - << "if (arg_val < INT_MIN || arg_val > INT_MAX) {\n"; - - error_raise_return(extra_convert, 2, return_flags, "OverflowError", - "value %ld out of range for signed integer", - "arg_val"); - - extra_convert - << "}\n" - << "#endif\n"; - - pexpr_string = "(" + type->get_local_name(&parser) + ")arg_val"; - - } else { - indent(out, indent_level) << "int " << param_name << default_expr << ";\n"; - format_specifiers += "i"; - parameter_list += ", &" + param_name; - } - expected_params += "int"; - only_pyobjects = false; - - } else if (TypeManager::is_double(type)) { - if (args_type == AT_single_arg) { - pexpr_string = "PyFloat_AsDouble(arg)"; - type_check = "PyNumber_Check(arg)"; - } else { - indent(out, indent_level) << "double " << param_name << default_expr << ";\n"; - format_specifiers += "d"; - parameter_list += ", &" + param_name; - } - expected_params += "double"; - only_pyobjects = false; - - } else if (TypeManager::is_float(type)) { - if (args_type == AT_single_arg) { - pexpr_string = "(" + type->get_local_name(&parser) + ")PyFloat_AsDouble(arg)"; - type_check = "PyNumber_Check(arg)"; - } else { - indent(out, indent_level) << "float " << param_name << default_expr << ";\n"; - format_specifiers += "f"; - parameter_list += ", &" + param_name; - } - expected_params += "float"; - only_pyobjects = false; - - } else if (TypeManager::is_const_char_pointer(type)) { - indent(out, indent_level) << "const char *" << param_name << default_expr << ";\n"; - format_specifiers += "z"; - parameter_list += ", &" + param_name; - expected_params += "buffer"; - only_pyobjects = false; - - } else if (TypeManager::is_pointer_to_PyTypeObject(type)) { - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << default_expr << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - pexpr_string = param_name; - } - extra_param_check << " && PyType_Check(" << param_name << ")"; - pexpr_string = "(PyTypeObject *)" + param_name; - expected_params += "type"; - - // It's reasonable to assume that a function taking a PyTypeObject might - // also throw a TypeError if the type is incorrect. - may_raise_typeerror = true; - - } else if (TypeManager::is_pointer_to_PyStringObject(type)) { - if (args_type == AT_single_arg) { - // This is a single-arg function, so there's no need to convert - // anything. - param_name = "arg"; - type_check = "PyString_Check(arg)"; - pexpr_string = "(PyStringObject *)" + param_name; - } else { - indent(out, indent_level) << "PyStringObject *" << param_name << default_expr << ";\n"; - format_specifiers += "S"; - parameter_list += ", &" + param_name; - pexpr_string = param_name; - } - expected_params += "string"; - - } else if (TypeManager::is_pointer_to_PyUnicodeObject(type)) { - if (args_type == AT_single_arg) { - // This is a single-arg function, so there's no need to convert - // anything. - param_name = "arg"; - type_check = "PyUnicode_Check(arg)"; - pexpr_string = "(PyUnicodeObject *)" + param_name; - } else { - indent(out, indent_level) << "PyUnicodeObject *" << param_name << default_expr << ";\n"; - format_specifiers += "U"; - parameter_list += ", &" + param_name; - pexpr_string = param_name; - } - expected_params += "unicode"; - - } else if (TypeManager::is_pointer_to_PyObject(type)) { - if (args_type == AT_single_arg) { - // This is a single-arg function, so there's no need to convert - // anything. - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << default_expr << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - pexpr_string = param_name; - expected_params += "object"; - - // It's reasonable to assume that a function taking a PyObject might - // also throw a TypeError if the type is incorrect. - may_raise_typeerror = true; - - } else if (TypeManager::is_pointer_to_Py_buffer(type)) { - min_version = 0x02060000; // Only support this remap in version 2.6+. - - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - indent(out, indent_level) << "Py_buffer " << param_name << "_view;\n"; - - if (is_optional) { - indent(out, indent_level) << "Py_buffer *" << param_name << "_viewp;\n"; - - extra_convert - << "bool " << param_name << "_success;\n" - << "if (" << param_name << " != nullptr) {\n" - << " " << param_name << "_success = (PyObject_GetBuffer(" - << param_name << ", &" << param_name << "_view, PyBUF_FULL) == 0);\n" - << " " << param_name << "_viewp = &" << param_name << "_view;\n" - << "} else {\n" - << " " << param_name << "_viewp" << default_expr << ";\n" - << " " << param_name << "_success = true;\n" - << "}\n"; - - extra_param_check << " && " << param_name << "_success"; - pexpr_string = param_name + "_viewp"; - extra_cleanup << "if (" << param_name << " != nullptr) PyBuffer_Release(&" << param_name << "_view);\n"; - } else { - extra_param_check << " && PyObject_GetBuffer(" - << param_name << ", &" - << param_name << "_view, PyBUF_FULL) == 0"; - pexpr_string = "&" + param_name + "_view"; - extra_cleanup << "PyBuffer_Release(&" << param_name << "_view);\n"; - } - expected_params += "buffer"; - may_raise_typeerror = true; - clear_error = true; - - } else if (TypeManager::is_pointer_to_simple(type)) { - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - indent(out, indent_level) << "Py_buffer " << param_name << "_view;\n"; - - // Unravel the type to determine its properties. - int array_len = -1; - bool is_const = true; - CPPSimpleType *simple = nullptr; - CPPType *unwrap = TypeManager::unwrap_const_reference(type); - if (unwrap != nullptr) { - CPPArrayType *array_type = unwrap->as_array_type(); - CPPPointerType *pointer_type = unwrap->as_pointer_type(); - - if (array_type != nullptr) { - if (array_type->_bounds != nullptr) { - array_len = array_type->_bounds->evaluate().as_integer(); - } - unwrap = array_type->_element_type; - } else if (pointer_type != nullptr) { - unwrap = pointer_type->_pointing_at; - } - - CPPConstType *const_type = unwrap->as_const_type(); - if (const_type != nullptr) { - unwrap = const_type->_wrapped_around; - } else { - is_const = false; - } - - while (unwrap->get_subtype() == CPPDeclaration::ST_typedef) { - unwrap = unwrap->as_typedef_type()->_type; - } - simple = unwrap->as_simple_type(); - } - - // Determine the format, so we can check the type of the buffer we get. - char format_chr = 'B'; - - switch (simple->_type) { - case CPPSimpleType::T_char: - if (simple->_flags & CPPSimpleType::F_unsigned) { - format_chr = 'B'; - } else if (simple->_flags & CPPSimpleType::F_signed) { - format_chr = 'b'; - } else { - format_chr = 'c'; - } - break; - - case CPPSimpleType::T_int: - if (simple->_flags & CPPSimpleType::F_longlong) { - format_chr = 'q'; - } else if (simple->_flags & CPPSimpleType::F_long) { - format_chr = 'l'; - } else if (simple->_flags & CPPSimpleType::F_short) { - format_chr = 'h'; - } else { - format_chr = 'i'; - } - - if (simple->_flags & CPPSimpleType::F_unsigned) { - format_chr &= 0x5f; // Uppercase - } - break; - - case CPPSimpleType::T_float: - format_chr = 'f'; - break; - - case CPPSimpleType::T_double: - format_chr = 'd'; - break; - - default: - nout << "Warning: cannot determine buffer format string for type " - << type->get_local_name(&parser) - << " (simple type " << *simple << ")\n"; - extra_param_check << " && false"; - } - - const char *flags; - if (format_chr == 'B') { - if (is_const) { - flags = "PyBUF_SIMPLE"; - } else { - flags = "PyBUF_WRITABLE"; - } - } else if (is_const) { - flags = "PyBUF_FORMAT"; - } else { - flags = "PyBUF_FORMAT | PyBUF_WRITABLE"; - } - - extra_param_check << " && PyObject_GetBuffer(" << param_name << ", &" - << param_name << "_view, " << flags << ") == 0"; - - if (format_chr != 'B') { - extra_param_check - << " && " << param_name << "_view.format[0] == '" << format_chr << "'" - << " && " << param_name << "_view.format[1] == 0"; - } - if (array_len != -1) { - extra_param_check - << " && " << param_name << "_view.len == " << array_len; - } - - pexpr_string = "(" + simple->get_local_name(&parser) + " *)" + - param_name + "_view.buf"; - - extra_cleanup << "PyBuffer_Release(&" << param_name << "_view);\n"; - expected_params += "buffer"; - clear_error = true; - - } else if (TypeManager::is_pointer(type)) { - CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(type)); - bool const_ok = !TypeManager::is_non_const_pointer_or_ref(orig_type); - - if (TypeManager::is_const_pointer_or_ref(orig_type)) { - expected_params += "const "; - // } else { expected_params += "non-const "; - } - string expected_class_name = classNameFromCppName(obj_type->get_simple_name(), false); - expected_params += expected_class_name; - - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - - // If the default value is NULL, we also accept a None value. - bool maybe_none = false; - if (default_value != nullptr && (return_flags & RF_coerced) == 0 && - TypeManager::is_pointer(orig_type)) { - CPPExpression::Result res = param->get_default_value()->evaluate(); - if (res._type == CPPExpression::RT_integer || - res._type == CPPExpression::RT_pointer) { - if (res.as_integer() == 0) { - maybe_none = true; - } - } - } - - string class_name = obj_type->get_local_name(&parser); - - // need to a forward scope for this class.. - if (!isExportThisRun(obj_type)) { - _external_imports.insert(TypeManager::resolve_type(obj_type)); - } - - string this_class_name; - string method_prefix; - if (remap->_cpptype) { - this_class_name = remap->_cpptype->get_simple_name(); - method_prefix = classNameFromCppName(this_class_name, false) + string("."); - } - - if (coercion_possible && - has_coerce_constructor(obj_type->as_struct_type())) { - // Call the coercion function directly, which will try to extract the - // pointer directly before trying coercion. - string coerce_call; - - if (TypeManager::is_reference_count(obj_type)) { - // We use a PointerTo to handle the management here. It's cleaner - // that way. - if (default_expr == " = 0" || default_expr == " = nullptr") { - default_expr.clear(); - } - if (TypeManager::is_const_pointer_to_anything(type)) { - extra_convert - << "CPT(" << class_name << ") " << param_name << "_this" - << default_expr << ";\n"; - - coerce_call = "Dtool_ConstCoerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_this)"; - } else { - extra_convert - << "PT(" << class_name << ") " << param_name << "_this" - << default_expr << ";\n"; - - coerce_call = "Dtool_Coerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_this)"; - } - - // Use move constructor when available for functions that take an - // actual PointerTo. This eliminates an unref()ref() pair. - pexpr_string = "std::move(" + param_name + "_this)"; - - } else { - // This is a move-assignable type, such as TypeHandle or LVecBase4. - obj_type->output_instance(extra_convert, param_name + "_local", &parser); - extra_convert << ";\n"; - - type->output_instance(extra_convert, param_name + "_this", &parser); - - if (is_optional && maybe_none) { - extra_convert - << default_expr << ";\n" - << "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n" - << " " << param_name << "_this"; - } else if (is_optional) { - if (TypeManager::is_pointer(orig_type)) { - extra_convert << default_expr; - } - extra_convert - << ";\n" - << "if (" << param_name << " != nullptr) {\n" - << " " << param_name << "_this"; - } else if (maybe_none) { - extra_convert - << " = nullptr;\n" - << "if (" << param_name << " != Py_None) {\n" - << " " << param_name << "_this"; - } - - extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) + - "(" + param_name + ", " + param_name + "_local);\n"; - - if (is_optional && !TypeManager::is_pointer(orig_type)) { - extra_convert - << "} else {\n" - << " " << param_name << "_local" << default_expr << ";\n" - << " " << param_name << "_this = &" << param_name << "_local;\n" - << "}\n"; - } else if (is_optional || maybe_none) { - extra_convert << "}\n"; - } - - coerce_call = "(" + param_name + "_this != nullptr)"; - - pexpr_string = param_name + "_this"; - } - - if (report_errors) { - // We were asked to report any errors. Let's do it. - if (is_optional && maybe_none) { - extra_convert << "if (" << param_name << " != nullptr && " << param_name << " != Py_None && !" << coerce_call << ") {\n"; - } else if (is_optional) { - extra_convert << "if (" << param_name << " != nullptr && !" << coerce_call << ") {\n"; - } else if (maybe_none) { - extra_convert << "if (" << param_name << " != Py_None && !" << coerce_call << ") {\n"; - } else { - extra_convert << "if (!" << coerce_call << ") {\n"; - } - - // Display error like: Class.func() argument 0 must be A, not B - if ((return_flags & ~RF_pyobject) == RF_err_null) { - // Dtool_Raise_ArgTypeError returns NULL already - extra_convert << " return "; - } else { - extra_convert << " "; - } - extra_convert - << "Dtool_Raise_ArgTypeError(" << param_name << ", " - << pn << ", \"" << method_prefix - << methodNameFromCppName(remap, this_class_name, false) - << "\", \"" << expected_class_name << "\");\n"; - - if ((return_flags & ~RF_pyobject) != RF_err_null) { - error_return(extra_convert, 2, return_flags); - } - extra_convert << "}\n"; - - } else if (is_optional && maybe_none) { - extra_param_check << " && (" << param_name << " == nullptr || " << param_name << " == Py_None || " << coerce_call << ")"; - - } else if (is_optional) { - extra_param_check << " && (" << param_name << " == nullptr || " << coerce_call << ")"; - - } else if (maybe_none) { - extra_param_check << " && (" << param_name << " == Py_None || " << coerce_call << ")"; - - } else { - extra_param_check << " && " << coerce_call; - } - - } else { // The regular, non-coercion case. - type->output_instance(extra_convert, param_name + "_this", &parser); - if (is_optional && maybe_none) { - // This parameter has a default value of nullptr, so we need to also - // allow passing in None. - extra_convert - << default_expr << ";\n" - << "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n" - << " " << param_name << "_this"; - } - else if (is_optional && !TypeManager::is_pointer(orig_type) && !default_value->is_lvalue()) { - // Most annoying case, where we have to use an rvalue reference to - // extend the lifetime of the default argument. In this case, the - // default expression is invoked even if not used. - extra_convert << ";\n"; - if (TypeManager::is_const_pointer_to_anything(type)) { - extra_convert << "const "; - obj_type->output_instance(extra_convert, "&" + param_name + "_ref", &parser); - } else { - obj_type->output_instance(extra_convert, "&&" + param_name + "_ref", &parser); - } - extra_convert - << default_expr << ";\n" - << "if (" << param_name << " == nullptr) {\n" - << " " << param_name << "_this = &" << param_name << "_ref;\n" - << "} else {\n" - << " " << param_name << "_this"; - } - else if (is_optional) { - // General case where the default argument is either an lvalue or a - // pointer. - extra_convert - << ";\n" - << "if (" << param_name << " == nullptr) {\n" - << " " << param_name << "_this = "; - if (TypeManager::is_pointer(orig_type)) { - default_value->output(extra_convert, 0, &parser, false); - extra_convert << ";\n"; - } else { - // The rvalue case was handled above, so this is an lvalue, which - // means we can safely take a reference to it. - extra_convert << "&("; - default_value->output(extra_convert, 0, &parser, false); - extra_convert << ");\n"; - } - extra_convert - << "} else {\n" - << " " << param_name << "_this"; - } - else if (maybe_none) { - // No default argument, but we still need to check for None. - extra_convert - << " = nullptr;\n" - << "if (" << param_name << " != Py_None) {\n" - << " " << param_name << "_this"; - } - - if (const_ok && !report_errors) { - // This function does the same thing in this case and is slightly - // simpler. But maybe we should just reorganize these functions - // entirely? - extra_convert << " = nullptr;\n"; - int indent_level = (is_optional || maybe_none) ? 2 : 0; - indent(extra_convert, indent_level) - << "DtoolInstance_GetPointer(" << param_name - << ", " << param_name << "_this" - << ", *Dtool_Ptr_" << make_safe_name(class_name) - << ");\n"; - } else { - extra_convert << std::boolalpha - << " = (" << class_name << " *)" - << "DTOOL_Call_GetPointerThisClass(" << param_name - << ", Dtool_Ptr_" << make_safe_name(class_name) - << ", " << pn << ", \"" - << method_prefix << methodNameFromCppName(remap, this_class_name, false) - << "\", " << const_ok << ", " << report_errors << ");\n"; - } - - if (is_optional && maybe_none) { - extra_convert << "}\n"; - extra_param_check << " && (" << param_name << " == nullptr || " << param_name << " == Py_None || " << param_name << "_this != nullptr)"; - } else if (is_optional) { - extra_convert << "}\n"; - extra_param_check << " && (" << param_name << " == nullptr || " << param_name << "_this != nullptr)"; - } else if (maybe_none) { - extra_convert << "}\n"; - extra_param_check << " && (" << param_name << " == Py_None || " << param_name << "_this != nullptr)"; - } else { - extra_param_check << " && " << param_name << "_this != nullptr"; - } - - pexpr_string = param_name + "_this"; - } - - } else { - // Ignore a parameter. - if (args_type == AT_single_arg) { - param_name = "arg"; - } else { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - expected_params += "any"; - } - - if (!reported_name.empty()) { - expected_params += " " + reported_name; - } - pexprs.push_back(pexpr_string); - } - expected_params += ")\n"; - - if (min_version > 0) { - out << "#if PY_VERSION_HEX >= 0x" << hex << min_version << dec << "\n"; - } - - // Track how many curly braces we've opened. - short open_scopes = 0; - - if (!type_check.empty() && args_type == AT_single_arg) { - indent(out, indent_level) - << "if (" << type_check << ") {\n"; - - ++open_scopes; - indent_level += 2; - - } else if (!format_specifiers.empty()) { - string method_name = methodNameFromCppName(remap, "", false); - - switch (args_type) { - case AT_keyword_args: - // Wrapper takes a varargs tuple and a keyword args dict. - if (has_keywords) { - if (only_pyobjects && max_num_args == 1) { - // But we are only expecting one object arg, which is an easy common - // case we have implemented ourselves. - if (min_num_args == 1) { - indent(out, indent_level) - << "if (Dtool_ExtractArg(&" << param_name << ", args, kwds, " << keyword_list_new << ")) {\n"; - } else { - indent(out, indent_level) - << "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds, " << keyword_list_new << ")) {\n"; - } - } else { - // We have to use the more expensive PyArg_ParseTupleAndKeywords. - clear_error = true; - if (keyword_list_new != keyword_list_old) { - out << "#if PY_VERSION_HEX >= 0x03060000\n"; - indent(out, indent_level) - << "static const char *keyword_list[] = {" << keyword_list_new << ", nullptr};\n"; - out << "#else\n"; - indent(out, indent_level) - << "static const char *keyword_list[] = {" << keyword_list_old << ", nullptr};\n"; - out << "#endif\n"; - } else { - indent(out, indent_level) - << "static const char *keyword_list[] = {" << keyword_list_new << ", nullptr};\n"; - } - indent(out, indent_level) - << "if (PyArg_ParseTupleAndKeywords(args, kwds, \"" - << format_specifiers << ":" << method_name - << "\", (char **)keyword_list" << parameter_list << ")) {\n"; - } - - } else if (only_pyobjects) { - // This function actually has no named parameters, so let's not take - // any keyword arguments. - if (max_num_args == 1) { - if (min_num_args == 1) { - indent(out, indent_level) - << "if (Dtool_ExtractArg(&" << param_name << ", args, kwds)) {\n"; - } else { - indent(out, indent_level) - << "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds)) {\n"; - } - } else if (max_num_args == 0) { - indent(out, indent_level) - << "if (Dtool_CheckNoArgs(args, kwds)) {\n"; - } else { - clear_error = true; - indent(out, indent_level) - << "if ((kwds == nullptr || PyDict_Size(kwds) == 0) && PyArg_UnpackTuple(args, \"" - << methodNameFromCppName(remap, "", false) - << "\", " << min_num_args << ", " << max_num_args - << parameter_list << ")) {\n"; - } - - } else { - clear_error = true; - indent(out, indent_level) - << "if ((kwds == nullptr || PyDict_Size(kwds) == 0) && PyArg_ParseTuple(args, \"" - << format_specifiers << ":" << method_name - << "\"" << parameter_list << ")) {\n"; - } - - ++open_scopes; - indent_level += 2; - break; - - case AT_varargs: - // Wrapper takes a varargs tuple. - if (only_pyobjects) { - // All parameters are PyObject*, so we can use the slightly more - // efficient PyArg_UnpackTuple function instead. - if (min_num_args == 1 && max_num_args == 1) { - indent(out, indent_level) - << "if (PyTuple_GET_SIZE(args) == 1) {\n"; - indent(out, indent_level + 2) - << param_name << " = PyTuple_GET_ITEM(args, 0);\n"; - } else { - clear_error = true; - indent(out, indent_level) - << "if (PyArg_UnpackTuple(args, \"" - << methodNameFromCppName(remap, "", false) - << "\", " << min_num_args << ", " << max_num_args - << parameter_list << ")) {\n"; - } - - } else { - clear_error = true; - indent(out, indent_level) - << "if (PyArg_ParseTuple(args, \"" - << format_specifiers << ":" << method_name - << "\"" << parameter_list << ")) {\n"; - } - ++open_scopes; - indent_level += 2; - break; - - case AT_single_arg: - // Single argument. If not a PyObject*, use PyArg_Parse. - if (!only_pyobjects && format_specifiers != "O") { - indent(out, indent_level) - << "if (PyArg_Parse(arg, \"" << format_specifiers << ":" - << method_name << "\"" << parameter_list << ")) {\n"; - - ++open_scopes; - clear_error = true; - indent_level += 2; - } - - default: - break; - } - } - - while (extra_convert.is_text_available()) { - string line = extra_convert.get_line(); - if (line.size() == 0 || line[0] == '#') { - out << line << "\n"; - } else { - indent(out, indent_level) << line << "\n"; - } - } - - string extra_param_check_str = extra_param_check.str(); - if (!extra_param_check_str.empty()) { - indent(out, indent_level) - << "if (" << extra_param_check_str.substr(4) << ") {\n"; - - ++open_scopes; - indent_level += 2; - } - - bool init_self_member = is_constructor && - (return_flags & RF_coerced) == 0 && - has_self_member(remap->_cpptype->as_struct_type()); - - if (init_self_member || (is_constructor && !remap->_has_this && - (remap->_flags & FunctionRemap::F_explicit_self) != 0)) { - // If we'll be passing "self" to the constructor, we need to pre- - // initialize it here. Unfortunately, we can't pre-load the "this" - // pointer, but the constructor itself can do this. - - CPPType *orig_type = remap->_return_type->get_orig_type(); - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); - const InterrogateType &itype = idb->get_type(type_index); - - indent(out, indent_level) - << "// Pre-initialize self for the constructor\n"; - - if (!is_constructor || (return_flags & RF_int) == 0) { - // This is not a constructor, but somehow we landed up here at a static - // method requiring a 'self' pointer. This happens in coercion - // constructors in particular. We'll have to create a temporary - // PyObject instance to pass to it. - - indent(out, indent_level) - << "PyObject *self = Dtool_new_" - << make_safe_name(itype.get_scoped_name()) << "(&" - << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) - << "._PyType, nullptr, nullptr);\n"; - - extra_cleanup << "PyObject_Del(self);\n"; - } else { - // XXX rdb: this isn't needed, is it, because tp_new already initializes - // the instance? - indent(out, indent_level) - << "DTool_PyInit_Finalize(self, nullptr, &" - << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) - << ", false, false);\n"; - } - } - - string return_expr; - - if (remap->_blocking) { - // With SIMPLE_THREADS, it's important that we never release the - // interpreter lock. - out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, indent_level) - << "PyThreadState *_save;\n"; - indent(out, indent_level) - << "Py_UNBLOCK_THREADS\n"; - out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; - } - if (track_interpreter) { - indent(out, indent_level) << "in_interpreter = 0;\n"; - } - - // If the function returns a pointer that we may need to manage, we store it - // in a temporary return_value variable and set this to true. - bool manage_return = false; - - if (remap->_return_type->new_type_is_atomic_string()) { - // Treat strings as a special case. We don't want to format the return - // expression. - return_expr = remap->call_function(out, indent_level, false, container, pexprs); - CPPType *type = remap->_return_type->get_orig_type(); - indent(out, indent_level); - type->output_instance(out, "return_value", &parser); - out << " = " << return_expr << ";\n"; - manage_return = remap->_return_value_needs_management; - return_expr = "return_value"; - - } else if ((return_flags & RF_coerced) != 0 && !TypeManager::is_reference_count(remap->_cpptype)) { - // Another special case is the coerce constructor for a trivial type. We - // don't want to invoke "operator new" unnecessarily. - if (is_constructor && remap->_extension) { - // Extension constructors are a special case, as usual. - indent(out, indent_level) - << remap->get_call_str("&coerced", pexprs) << ";\n"; - - } else { - indent(out, indent_level) - << "coerced = " << remap->get_call_str(container, pexprs) << ";\n"; - } - return_expr = "&coerced"; - - } else if (is_constructor && (return_flags & RF_coerced) == 0 && - is_python_subclassable(remap->_cpptype->as_struct_type())) { - // Add special code to detect whether we're trying to create a subclass - // of this object. If so, create a proxy instance instead. - CPPType *orig_type = remap->_return_type->get_orig_type(); - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); - const InterrogateType &itype = idb->get_type(type_index); - std::string safe_name = make_safe_name(itype.get_scoped_name()); - - CPPType *type = remap->_return_type->get_temporary_type(); - type->output_instance(indent(out, indent_level), "return_value", &parser); - out << ";\n"; - - indent(out, indent_level) - << "if (Py_TYPE(self) != &Dtool_" << safe_name << "._PyType) {\n"; - indent(out, indent_level) - << " DtoolProxy_" << safe_name << " *proxy = new DtoolProxy_" << safe_name << "("; - remap->write_call_args(out, pexprs); - out << ");\n"; - indent(out, indent_level) - << " DtoolProxy_Init(proxy, self, Dtool_" << safe_name << ", &Dtool_WrapProxy_" << safe_name << ");\n"; - indent(out, indent_level) - << " return_value = proxy;\n"; - indent(out, indent_level) - << "} else {\n"; - - return_expr = remap->call_function(out, indent_level, true, container, pexprs); - indent(out, indent_level) - << " return_value = " << return_expr << ";\n"; - indent(out, indent_level) - << "}\n"; - - return_expr = "return_value"; - manage_return = true; - - } else { - // The general case; an ordinary constructor or function. - return_expr = remap->call_function(out, indent_level, true, container, pexprs); - - if ((return_flags & RF_self) != 0) { - if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) { - // If the function returns a PyObject *, let it override the default - // behavior of returning self. - return_flags = (return_flags & ~RF_self) | RF_pyobject; - } else { - // We won't be using the return value, anyway. - return_expr.clear(); - } - } - - if (!return_expr.empty()) { - manage_return = remap->_return_value_needs_management; - CPPType *type = remap->_return_type->get_temporary_type(); - indent(out, indent_level); - type->output_instance(out, "return_value", &parser); - out << " = " << return_expr << ";\n"; - return_expr = "return_value"; - } - } - - // Clean up any memory we might have allocate for parsing the parameters. - while (extra_cleanup.is_text_available()) { - string line = extra_cleanup.get_line(); - if (line.size() == 0 || line[0] == '#') { - out << line << "\n"; - } else { - indent(out, indent_level) << line << "\n"; - } - } - - if (track_interpreter) { - indent(out, indent_level) << "in_interpreter = 1;\n"; - } - if (remap->_blocking) { - out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, indent_level) - << "Py_BLOCK_THREADS\n"; - out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; - } - - if (manage_return) { - // If a constructor returns NULL, that means allocation failed. - if (remap->_return_type->return_value_needs_management()) { - indent(out, indent_level) << "if (return_value == nullptr) {\n"; - if ((return_flags & ~RF_pyobject) == RF_err_null) { - // PyErr_NoMemory returns NULL, so allow tail call elimination. - indent(out, indent_level) << " return PyErr_NoMemory();\n"; - } else { - indent(out, indent_level) << " PyErr_NoMemory();\n"; - error_return(out, indent_level + 2, return_flags); - } - indent(out, indent_level) << "}\n"; - } - - if (init_self_member) { - indent(out, indent_level) - << "return_value->__self__ = Py_NewRef(self);\n"; - } - - if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) { - return_expr = "Py_XNewRef(return_value)"; - } else { - return_expr = manage_return_value(out, indent_level, remap, "return_value"); - } - return_expr = remap->_return_type->temporary_to_return(return_expr); - } - - // How could we raise a TypeError if we don't take any args? - if (args_type == AT_no_args || max_num_args == 0) { - may_raise_typeerror = false; - } - - // If a function takes a PyObject* argument, it would be a good idea to - // always check for exceptions. - if (may_raise_typeerror) { - check_exceptions = true; - } - - // Generated getters and setters don't raise exceptions or asserts since - // they don't contain any code. - if (remap->_type == FunctionRemap::T_getter || - remap->_type == FunctionRemap::T_setter) { - check_exceptions = false; - } - - // The most common case of the below logic is consolidated in a single - // function, as another way to reduce code bloat. Sigh. - if (check_exceptions && (!may_raise_typeerror || report_errors) && - watch_asserts && (return_flags & RF_coerced) == 0) { - - if (return_flags & RF_decref_args) { - indent(out, indent_level) << "Py_DECREF(args);\n"; - return_flags &= ~RF_decref_args; - } - - // An even specialer special case for functions with void return or bool - // return. We have our own functions that do all this in a single - // function call, so it should reduce the amount of code output while not - // being any slower. - bool return_null = (return_flags & RF_pyobject) != 0 && - (return_flags & RF_err_null) != 0 && - (return_flags & RF_richcompare_zero) == 0; - if (return_null && return_expr.empty()) { - indent(out, indent_level) - << "return Dtool_Return_None();\n"; - - // Reset the return value bit so that the code below doesn't generate - // the return statement a second time. - return_flags &= ~RF_pyobject; - - } else if (return_null && TypeManager::is_bool(remap->_return_type->get_new_type())) { - if (return_flags & RF_invert_bool) { - indent(out, indent_level) - << "return Dtool_Return_Bool(!(" << return_expr << "));\n"; - } else { - indent(out, indent_level) - << "return Dtool_Return_Bool(" << return_expr << ");\n"; - } - return_flags &= ~RF_pyobject; - - } else if (return_null && TypeManager::is_pointer_to_PyObject(remap->_return_type->get_new_type())) { - indent(out, indent_level) - << "return Dtool_Return(" << return_expr << ");\n"; - return_flags &= ~RF_pyobject; - - } else { - indent(out, indent_level) - << "if (Dtool_CheckErrorOccurred()) {\n"; - - if (manage_return) { - delete_return_value(out, indent_level + 2, remap, return_expr); - } - error_return(out, indent_level + 2, return_flags); - - indent(out, indent_level) << "}\n"; - } - - } else { - if (check_exceptions) { - // Check if a Python exception has occurred. We only do this when - // check_exception is set. If report_errors is set, this method must - // terminate on error. - if (!may_raise_typeerror || report_errors) { - indent(out, indent_level) - << "if (PyErr_Occurred()) {\n"; - } else { - // If a method is some extension method that takes a PyObject*, and it - // raised a TypeError, continue. The documentation tells us not to - // compare the result of PyErr_Occurred against a specific exception - // type. However, in our case, this seems okay because we know that - // the TypeError we want to catch here is going to be generated by a - // PyErr_SetString call, not by user code. - indent(out, indent_level) - << "PyObject *exception = PyErr_Occurred();\n"; - indent(out, indent_level) - << "if (exception == PyExc_TypeError) {\n"; - indent(out, indent_level) - << " // TypeError raised; continue to next overload type.\n"; - indent(out, indent_level) - << "} else if (exception != nullptr) {\n"; - } - - if (manage_return) { - delete_return_value(out, indent_level + 2, remap, return_expr); - } - - error_return(out, indent_level + 2, return_flags); - - indent(out, indent_level) - << "} else {\n"; - - ++open_scopes; - indent_level += 2; - } - - if (return_flags & RF_decref_args) { - indent(out, indent_level) << "Py_DECREF(args);\n"; - return_flags &= ~RF_decref_args; - } - - // Outputs code to check to see if an assertion has failed while the C++ - // code was executing, and report this failure back to Python. Don't do - // this for coercion constructors since they are called by other wrapper - // functions which already check this on their own. Generated getters - // obviously can't raise asserts. - if (watch_asserts && (return_flags & (RF_coerced | RF_raise_keyerror)) == 0 && - remap->_type != FunctionRemap::T_getter && - remap->_type != FunctionRemap::T_setter) { - out << "#ifndef NDEBUG\n"; - indent(out, indent_level) - << "Notify *notify = Notify::ptr();\n"; - indent(out, indent_level) - << "if (UNLIKELY(notify->has_assert_failed())) {\n"; - - if (manage_return) { - // Output code to delete any temporary object we may have allocated. - delete_return_value(out, indent_level + 2, remap, return_expr); - } - - if (return_flags & RF_err_null) { - // This function returns NULL, so we can pass it on. - indent(out, indent_level + 2) - << "return Dtool_Raise_AssertionError();\n"; - } else { - indent(out, indent_level + 2) - << "Dtool_Raise_AssertionError();\n"; - error_return(out, indent_level + 2, return_flags); - } - - indent(out, indent_level) - << "}\n"; - out << "#endif\n"; - } - } - - // Okay, we're past all the error conditions and special cases. Now return - // the return type in the way that was requested. - if ((return_flags & RF_int) != 0 && (return_flags & RF_raise_keyerror) == 0) { - CPPType *orig_type = remap->_return_type->get_orig_type(); - if (is_constructor) { - // Special case for constructor. - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); - const InterrogateType &itype = idb->get_type(type_index); - indent(out, indent_level) - << "return DTool_PyInit_Finalize(self, (void *)" << return_expr << ", &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", true, false);\n"; - - } else if (TypeManager::is_bool(orig_type)) { - // It's an error return boolean, I guess. Return 0 on success. - indent(out, indent_level) << "return (" << return_expr << ") ? 0 : -1;\n"; - - } else if (TypeManager::is_integer(orig_type)) { - if ((return_flags & RF_compare) == RF_compare) { - // Make sure it returns -1, 0, or 1, or Python complains with: - // RuntimeWarning: tp_compare didn't return -1, 0 or 1 - indent(out, indent_level) << "return (int)(" << return_expr << " > 0) - (int)(" << return_expr << " < 0);\n"; - } else { - indent(out, indent_level) << "return " << return_expr << ";\n"; - } - - } else if (TypeManager::is_void(orig_type)) { - indent(out, indent_level) << "return 0;\n"; - - } else { - nout << "Warning: function has return type " << *orig_type - << ", expected int or void:\n" << expected_params << "\n"; - indent(out, indent_level) << "// Don't know what to do with return type " - << *orig_type << ".\n"; - indent(out, indent_level) << "return 0;\n"; - } - - } else if (return_flags & RF_self) { - indent(out, indent_level) << "return Py_NewRef(self);\n"; - - } else if (return_flags & RF_richcompare_zero) { - indent(out, indent_level) - << "Py_RETURN_RICHCOMPARE(" << return_expr << ", 0, op);\n"; - - } else if (return_flags & RF_pyobject) { - if (return_expr.empty()) { - indent(out, indent_level) << "return Py_NewRef(Py_None);\n"; - - } else if (return_flags & RF_preserve_null) { - indent(out, indent_level) << "if (" << return_expr << " == nullptr) {\n"; - indent(out, indent_level) << " return nullptr;\n"; - indent(out, indent_level) << "} else {\n"; - pack_return_value(out, indent_level + 2, remap, return_expr, return_flags); - indent(out, indent_level) << "}\n"; - - } else { - pack_return_value(out, indent_level, remap, return_expr, return_flags); - } - - } else if (return_flags & RF_coerced) { - // We were asked to assign the result to a "coerced" reference. - CPPType *return_type = remap->_cpptype; - CPPType *orig_type = remap->_return_type->get_orig_type(); - - // Special case for static make function that returns a pointer: cast the - // pointer to the right pointer type. - if (!is_constructor && (remap->_flags & FunctionRemap::F_coerce_constructor) != 0 && - (TypeManager::is_pointer(orig_type) || TypeManager::is_pointer_to_base(orig_type))) { - - CPPType *new_type = remap->_return_type->get_new_type(); - - if (TypeManager::is_const_pointer_to_anything(new_type)) { - return_type = CPPType::new_type(new CPPConstType(return_type)); - } - - if (IsPandaTypedObject(return_type->as_struct_type())) { - return_expr = "DCAST(" - + return_type->get_local_name(&parser) - + ", " + return_expr + ")"; - - } else { - return_type = CPPType::new_type(new CPPPointerType(return_type)); - return_expr = "(" + return_type->get_local_name(&parser) + - ") " + return_expr; - } - } - - if (return_expr == "coerced") { - // We already did this earlier... - indent(out, indent_level) << "return true;\n"; - - } else if (TypeManager::is_reference_count(remap->_cpptype)) { - indent(out, indent_level) << "coerced = std::move(" << return_expr << ");\n"; - indent(out, indent_level) << "return true;\n"; - - } else { - indent(out, indent_level) << "return &coerced;\n"; - } - - } else if (return_flags & RF_raise_keyerror) { - CPPType *orig_type = remap->_return_type->get_orig_type(); - - if (TypeManager::is_bool(orig_type) || TypeManager::is_pointer(orig_type)) { - indent(out, indent_level) << "if (!" << return_expr << ") {\n"; - } else if (TypeManager::is_unsigned_integer(orig_type)) { - indent(out, indent_level) << "if ((int)" << return_expr << " == -1) {\n"; - } else if (TypeManager::is_integer(orig_type)) { - indent(out, indent_level) << "if (" << return_expr << " < 0) {\n"; - } else { - indent(out, indent_level) << "if (false) {\n"; - } - - if (args_type == AT_single_arg) { - indent(out, indent_level) << " PyErr_SetObject(PyExc_KeyError, arg);\n"; - } else { - indent(out, indent_level) << " PyErr_SetObject(PyExc_KeyError, key);\n"; - } - error_return(out, indent_level + 2, return_flags); - indent(out, indent_level) << "}\n"; - } - - // If we were in a scope - bool always_returns = true; - if (open_scopes > 0) { - always_returns = false; - - // Close the extra braces opened earlier. - while (open_scopes > 0) { - indent_level -= 2; - indent(out, indent_level) << "}\n"; - - --open_scopes; - } - } - - if (clear_error && !report_errors) { - // We were asked not to report errors, so clear the active exception if - // this overload might have raised a TypeError. - indent(out, indent_level) << "PyErr_Clear();\n"; - } - - if (min_version > 0) { - // Close the #if PY_VERSION_HEX check. - out << "#endif\n"; - always_returns = false; - } - - return always_returns; -} - -/** - * Outputs the correct return statement that should be used in case of error - * based on the ReturnFlags. - */ -void InterfaceMakerPythonNative:: -error_return(ostream &out, int indent_level, int return_flags) { - // if (return_flags & RF_coerced) { indent(out, indent_level) << "coerced = - // NULL;\n"; } - - if (return_flags & RF_decref_args) { - indent(out, indent_level) << "Py_DECREF(args);\n"; - } - - if (return_flags & RF_int) { - indent(out, indent_level) << "return -1;\n"; - - } else if (return_flags & RF_err_notimplemented) { - indent(out, indent_level) << "return Py_NewRef(Py_NotImplemented);\n"; - - } else if (return_flags & RF_err_null) { - indent(out, indent_level) << "return nullptr;\n"; - - } else if (return_flags & RF_err_false) { - indent(out, indent_level) << "return false;\n"; - } -} - -/** - * Similar to error_return, except raises a "bad arguments" error before - * returning, if the error indicator has not yet been set. - */ -void InterfaceMakerPythonNative:: -error_bad_args_return(ostream &out, int indent_level, int return_flags, - const string &expected_params) { - - if (return_flags & RF_decref_args) { - indent(out, indent_level) << "Py_DECREF(args);\n"; - } - - if ((return_flags & RF_err_null) != 0 && - (return_flags & RF_pyobject) != 0) { - // It always returns nullptr, so we'll allow the compiler to do a tail - // call optimization. - indent(out, indent_level) << "return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, indent_level + 2, expected_params); - out << ");\n"; - return; - } - - if (return_flags & RF_int) { - // Same, but for -1. - indent(out, indent_level) << "return Dtool_Raise_BadArgumentsError_Int(\n"; - output_quoted(out, indent_level + 2, expected_params); - out << ");\n"; - return; - } - - indent(out, indent_level) << "Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, indent_level + 2, expected_params); - out << ");\n"; - - if (return_flags & RF_int) { - indent(out, indent_level) << "return -1;\n"; - - } else if (return_flags & RF_err_notimplemented) { - indent(out, indent_level) << "return Py_NewRef(Py_NotImplemented);\n"; - - } else if (return_flags & RF_err_null) { - indent(out, indent_level) << "return nullptr;\n"; - - } else if (return_flags & RF_err_false) { - indent(out, indent_level) << "return false;\n"; - } -} - -/** - * Similar to error_return, except raises an exception before returning. If - * format_args are not the empty string, uses PyErr_Format instead of - * PyErr_SetString. - */ -void InterfaceMakerPythonNative:: -error_raise_return(ostream &out, int indent_level, int return_flags, - const string &exc_type, const string &message, - const string &format_args) { - - if (return_flags & RF_decref_args) { - indent(out, indent_level) << "Py_DECREF(args);\n"; - return_flags &= ~RF_decref_args; - } - - if (format_args.empty()) { - if (exc_type == "TypeError") { - if ((return_flags & RF_err_null) != 0) { - // This is probably an over-optimization, but why the heck not. - indent(out, indent_level) << "return Dtool_Raise_TypeError("; - output_quoted(out, indent_level + 29, message, false); - out << ");\n"; - return; - } else { - indent(out, indent_level) << "Dtool_Raise_TypeError("; - output_quoted(out, indent_level + 22, message, false); - out << ");\n"; - } - } else { - indent(out, indent_level) << "PyErr_SetString(PyExc_" << exc_type << ",\n"; - output_quoted(out, indent_level + 16, message); - out << ");\n"; - } - - } else if ((return_flags & RF_err_null) != 0 && - (return_flags & RF_pyobject) != 0) { - // PyErr_Format always returns NULL. Passing it on directly allows the - // compiler to make a tiny optimization, so why not. - indent(out, indent_level) << "return PyErr_Format(PyExc_" << exc_type << ",\n"; - output_quoted(out, indent_level + 20, message); - out << ",\n"; - indent(out, indent_level + 20) << format_args << ");\n"; - return; - - } else { - indent(out, indent_level) << "PyErr_Format(PyExc_" << exc_type << ",\n"; - output_quoted(out, indent_level + 13, message); - out << ",\n"; - indent(out, indent_level + 13) << format_args << ");\n"; - } - - error_return(out, indent_level, return_flags); -} - -/** - * Outputs a command to pack the indicated expression, of the return_type - * type, as a Python return value. - */ -void InterfaceMakerPythonNative:: -pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, - string return_expr, int return_flags) { - - ParameterRemap *return_type = remap->_return_type; - CPPType *orig_type = return_type->get_orig_type(); - CPPType *type = return_type->get_new_type(); - - if (TypeManager::is_scoped_enum(type)) { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); - const InterrogateType &itype = idb->get_type(type_index); - string safe_name = make_safe_name(itype.get_scoped_name()); - - indent(out, indent_level) - << "return PyObject_CallFunction((PyObject *)Dtool_Ptr_" << safe_name; - - CPPType *underlying_type = ((CPPEnumType *)itype._cpptype)->get_underlying_type(); - if (TypeManager::is_unsigned_integer(underlying_type)) { - out << ", \"k\", (unsigned long)"; - } else { - out << ", \"l\", (long)"; - } - out << "(" << return_expr << "));\n"; - - } else if (return_type->new_type_is_atomic_string() || - TypeManager::is_simple(type) || - TypeManager::is_char_pointer(type) || - TypeManager::is_wchar_pointer(type) || - TypeManager::is_pointer_to_PyObject(type) || - TypeManager::is_pointer_to_Py_buffer(type) || - TypeManager::is_vector_unsigned_char(type)) { - // Most types are now handled by the many overloads of Dtool_WrapValue, - // defined in py_panda.h. - if (return_flags & RF_invert_bool) { - indent(out, indent_level) - << "return Dtool_WrapValue(!(" << return_expr << "));\n"; - } - else { - indent(out, indent_level) - << "return Dtool_WrapValue(" << return_expr << ");\n"; - } - } else if (TypeManager::is_pointer(type)) { - bool is_const = TypeManager::is_const_pointer_to_anything(type); - bool owns_memory = remap->_return_value_needs_management; - - // Note, we don't check for NULL here any more. This is now done by the - // appropriate CreateInstance(Typed) function. - - if (manage_reference_counts && TypeManager::is_pointer_to_base(orig_type)) { - // Use a trick to transfer the reference count to avoid a pair of - // unnecessary ref() and unref() calls. Ideally we'd use move - // semantics, but py_panda.cxx cannot make use of PointerTo. - indent(out, indent_level) << "// Transfer ownership of return_value.\n"; - indent(out, indent_level); - type->output_instance(out, "return_ptr", &parser); - out << " = " << return_expr << ";\n"; - indent(out, indent_level) << "return_value.cheat() = nullptr;\n"; - return_expr = "return_ptr"; - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - if (TypeManager::is_struct(orig_type) || TypeManager::is_ref_to_anything(orig_type)) { - if (TypeManager::is_ref_to_anything(orig_type) || remap->_manage_reference_count) { - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); - const InterrogateType &itype = idb->get_type(type_index); - - write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); - - } else { - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); - const InterrogateType &itype = idb->get_type(type_index); - - write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); - } - } else if (TypeManager::is_struct(orig_type->remove_pointer())) { - TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); - const InterrogateType &itype = idb->get_type(type_index); - - write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); - - } else { - indent(out, indent_level) << "Should Never Reach This InterfaceMakerPythonNative::pack_python_value"; - // << "return Dtool_Integer((int) " << return_expr << ");\n"; - } - - } else { - // Return None. - indent(out, indent_level) - << "return Py_BuildValue(\"\"); // Don't know how to wrap type.\n"; - } -} - -/** - * Generates the synthetic method described by the MAKE_SEQ() macro. - */ -void InterfaceMakerPythonNative:: -write_make_seq(ostream &out, Object *obj, const std::string &ClassName, - const std::string &cClassName, MakeSeq *make_seq) { - - out << "/*\n" - " * Python make_seq wrapper\n" - " */\n"; - - out << "static PyObject *" << make_seq->_name + "(PyObject *self, PyObject *) {\n"; - - // This used to return a list. But it should really be a tuple, I think, - // because it probably makes more sense for it to be immutable (as changes - // to it won't be visible on the C++ side anyway). - - FunctionRemap *remap = make_seq->_length_getter->_remaps.front(); - vector_string pexprs; - - if (make_seq->_length_getter->_has_this) { - out << - " " << cClassName << " *local_this = nullptr;\n" - " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" - " return nullptr;\n" - " }\n" - " Py_ssize_t count = (Py_ssize_t)" << remap->get_call_str("local_this", pexprs) << ";\n"; - } else { - out << " Py_ssize_t count = (Py_ssize_t)" << remap->get_call_str("", pexprs) << ";\n"; - } - - Function *elem_getter = make_seq->_element_getter; - - if ((elem_getter->_args_type & AT_varargs) == AT_varargs) { - // Fast way to create a temporary tuple to hold only a single item, under - // the assumption that the called method doesn't do anything with this - // tuple other than unpack it (which is a fairly safe assumption to make). - out << " PyTupleObject args;\n"; - out << " (void)PyObject_INIT_VAR((PyVarObject *)&args, &PyTuple_Type, 1);\n"; - } - - out << - " PyObject *tuple = PyTuple_New(count);\n" - "\n" - " for (Py_ssize_t i = 0; i < count; ++i) {\n" - " PyObject *index = Dtool_WrapValue(i);\n"; - - switch (elem_getter->_args_type) { - case AT_keyword_args: - out << " PyTuple_SET_ITEM(&args, 0, index);\n" - " PyObject *value = " << elem_getter->_name << "(self, (PyObject *)&args, nullptr);\n"; - break; - - case AT_varargs: - out << " PyTuple_SET_ITEM(&args, 0, index);\n" - " PyObject *value = " << elem_getter->_name << "(self, (PyObject *)&args);\n"; - break; - - case AT_single_arg: - out << " PyObject *value = " << elem_getter->_name << "(self, index);\n"; - break; - - default: - out << " PyObject *value = " << elem_getter->_name << "(self, nullptr);\n"; - break; - } - - out << - " PyTuple_SET_ITEM(tuple, i, value);\n" - " Py_DECREF(index);\n" - " }\n" - "\n"; - - if ((elem_getter->_args_type & AT_varargs) == AT_varargs) { - out << "#if defined(Py_TRACE_REFS) || PY_VERSION_HEX < 0x03090000\n"; - out << " _Py_ForgetReference((PyObject *)&args);\n"; - out << "#endif\n"; - } - - out << - " if (Dtool_CheckErrorOccurred()) {\n" - " Py_DECREF(tuple);\n" - " return nullptr;\n" - " }\n" - " return tuple;\n" - "}\n" - "\n"; -} - -/** - * Generates the synthetic method described by the MAKE_PROPERTY() macro. - */ -void InterfaceMakerPythonNative:: -write_getset(ostream &out, Object *obj, Property *property) { - // We keep around this empty vector for passing to get_call_str. - const vector_string pexprs; - - string ClassName = make_safe_name(obj->_itype.get_scoped_name()); - std::string cClassName = obj->_itype.get_true_name(); - - const InterrogateElement &ielem = property->_ielement; - - FunctionRemap *len_remap = nullptr; - if (property->_length_function != nullptr) { - assert(!property->_length_function->_remaps.empty()); - - // This is actually a sequence. Wrap this with a special class. - len_remap = property->_length_function->_remaps.front(); - - out << "/**\n" - " * sequence length function for property " << ielem.get_scoped_name() << "\n" - " */\n" - "static Py_ssize_t Dtool_" + ClassName + "_" + ielem.get_name() + "_Len(PyObject *self) {\n"; - if (property->_length_function->_has_this) { - out << - " " << cClassName << " *local_this = nullptr;\n" - " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" - " return -1;\n" - " }\n" - " return (Py_ssize_t)" << len_remap->get_call_str("local_this", pexprs) << ";\n"; - } else { - out << " return (Py_ssize_t)" << len_remap->get_call_str("", pexprs) << ";\n"; - } - out << "}\n\n"; - } - - if (property->_getter_remaps.empty()) { - return; - } - - if (ielem.is_sequence()) { - assert(len_remap != nullptr); - out << - "/**\n" - " * sequence getter for property " << ielem.get_scoped_name() << "\n" - " */\n" - "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Sequence_Getitem(PyObject *self, Py_ssize_t index) {\n"; - - if (property->_has_this) { - out << - " " << cClassName << " *local_this = nullptr;\n" - " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" - " return nullptr;\n" - " }\n"; - } - - // This is a getitem of a sequence type. This means we *need* to raise - // IndexError if we're out of bounds. - out << " if (index < 0 || index >= (Py_ssize_t)" - << len_remap->get_call_str("local_this", pexprs) << ") {\n"; - out << "#ifdef NDEBUG\n"; - out << " PyErr_SetString(PyExc_IndexError, \"index out of range\");\n"; - out << "#else\n"; - out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n"; - out << "#endif\n"; - out << " return nullptr;\n"; - out << " }\n"; - - /*if (property->_has_function != NULL) { - out << " if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n" - << " return Py_NewRef(Py_None);\n" - << " }\n"; - }*/ - - std::set remaps; - - // Extract only the getters that take one integral argument. - for (FunctionRemap *remap : property->_getter_remaps) { - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (min_num_args <= 1 && max_num_args >= 1 && - TypeManager::is_integer(remap->_parameters[(size_t)remap->_has_this]._remap->get_new_type())) { - remaps.insert(remap); - } - } - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { - error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); - } - out << "}\n\n"; - - // Write out a setitem if this is not a read-only property. - if (!property->_setter_remaps.empty()) { - out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Sequence_Setitem(PyObject *self, Py_ssize_t index, PyObject *arg) {\n"; - if (property->_has_this) { - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" - << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - } - - out << " if (index < 0 || index >= (Py_ssize_t)" - << len_remap->get_call_str("local_this", pexprs) << ") {\n"; - out << "#ifdef NDEBUG\n"; - out << " PyErr_SetString(PyExc_IndexError, \"index out of range\");\n"; - out << "#else\n"; - out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n"; - out << "#endif\n"; - out << " return -1;\n"; - out << " }\n"; - - out << " if (arg == nullptr) {\n"; - if (property->_deleter != nullptr) { - if (property->_deleter->_has_this) { - out << " local_this->" << property->_deleter->_ifunc.get_name() << "(index);\n"; - } else { - out << " " << cClassName << "::" << property->_deleter->_ifunc.get_name() << "(index);\n"; - } - out << " return 0;\n"; - } else { - out << "#ifdef NDEBUG\n" - " Dtool_Raise_TypeError(\"can't delete attribute\");\n" - "#else\n" - " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n" - "#endif\n" - " return -1;\n"; - } - out << " }\n"; - - if (property->_clear_function != nullptr) { - out << " if (arg == Py_None) {\n"; - if (property->_clear_function->_has_this) { - out << " local_this->" << property->_clear_function->_ifunc.get_name() << "(index);\n"; - } else { - out << " " << cClassName << "::" << property->_clear_function->_ifunc.get_name() << "(index);\n"; - } - out << " return 0;\n" - << " }\n"; - } - - std::set remaps; - - // Extract only the setters that take two arguments. - for (FunctionRemap *remap : property->_setter_remaps) { - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (min_num_args <= 2 && max_num_args >= 2 && - TypeManager::is_integer(remap->_parameters[1]._remap->get_new_type())) { - remaps.insert(remap); - } - } - - string expected_params; - if (!write_function_forset(out, remaps, 2, 2, expected_params, 2, true, - true, AT_single_arg, RF_int, false, false, "index")) { - error_bad_args_return(out, 2, RF_int, expected_params); - } - out << "}\n\n"; - } - - // Finally, add the inserter, if one exists. - if (property->_inserter != nullptr) { - out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Sequence_insert(PyObject *self, size_t index, PyObject *arg) {\n"; - if (property->_has_this) { - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" - << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; - out << " return nullptr;\n"; - out << " }\n\n"; - } - - std::set remaps; - remaps.insert(property->_inserter->_remaps.begin(), - property->_inserter->_remaps.end()); - - string expected_params; - if (!write_function_forset(out, remaps, 2, 2, expected_params, 2, true, - true, AT_single_arg, RF_pyobject | RF_err_null, - false, false, "index")) { - error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); - } - out << "}\n\n"; - } - } - - - // Write the getitem functions. - if (ielem.is_mapping()) { - out << - "/**\n" - " * mapping getitem for property " << ielem.get_scoped_name() << "\n" - " */\n" - "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Mapping_Getitem(PyObject *self, PyObject *arg) {\n"; - - // Before we do the has_function: if this is also a sequence, then we have - // to also handle the case here that we were passed an index. - if (ielem.is_sequence()) { - out << - "#if PY_MAJOR_VERSION >= 3\n" - " if (PyLong_CheckExact(arg)) {\n" - "#else\n" - " if (PyLong_CheckExact(arg) || PyInt_CheckExact(arg)) {\n" - "#endif\n" - " return Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem(self, PyLongOrInt_AsSize_t(arg));\n" - " }\n\n"; - } - - if (property->_has_this) { - out << - " " << cClassName << " *local_this = nullptr;\n" - " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" - " return nullptr;\n" - " }\n"; - } - - if (property->_has_function != nullptr) { - std::set remaps; - remaps.insert(property->_has_function->_remaps.begin(), - property->_has_function->_remaps.end()); - - out << " {\n"; - string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 4, true, true, - AT_single_arg, RF_raise_keyerror | RF_err_null, false, true); - out << " }\n"; - } - - std::set remaps; - // Extract only the getters that take one argument. Fish out the ones - // already taken by the sequence getter. - for (FunctionRemap *remap : property->_getter_remaps) { - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (min_num_args <= 1 && max_num_args >= 1 && - (!ielem.is_sequence() || !TypeManager::is_integer(remap->_parameters[(size_t)remap->_has_this]._remap->get_new_type()))) { - remaps.insert(remap); - } - } - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_pyobject | RF_err_null, false, true)) { - error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); - } - out << "}\n\n"; - - // Write out a setitem if this is not a read-only property. - if (!property->_setter_remaps.empty()) { - out << - "/**\n" - " * mapping setitem for property " << ielem.get_scoped_name() << "\n" - " */\n" - "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Mapping_Setitem(PyObject *self, PyObject *key, PyObject *value) {\n"; - - if (property->_has_this) { - out << - " " << cClassName << " *local_this = nullptr;\n" - " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" - << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n" - " return -1;\n" - " }\n\n"; - } - - out << " if (value == nullptr) {\n"; - if (property->_deleter != nullptr) { - out << " PyObject *arg = key;\n"; - - if (property->_has_function != nullptr) { - std::set remaps; - remaps.insert(property->_has_function->_remaps.begin(), - property->_has_function->_remaps.end()); - - out << " {\n"; - string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 6, true, true, - AT_single_arg, RF_raise_keyerror | RF_int, false, true); - out << " }\n"; - } - - std::set remaps; - remaps.insert(property->_deleter->_remaps.begin(), - property->_deleter->_remaps.end()); - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, - expected_params, 4, true, true, AT_single_arg, - RF_int, false, false)) { - out << " return -1;\n"; - } - } else { - out << "#ifdef NDEBUG\n" - " Dtool_Raise_TypeError(\"can't delete attribute\");\n" - "#else\n" - " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n" - "#endif\n" - " return -1;\n"; - } - out << " }\n"; - - if (property->_clear_function != nullptr) { - out << " if (value == Py_None) {\n" - << " local_this->" << property->_clear_function->_ifunc.get_name() << "(key);\n" - << " return 0;\n" - << " }\n"; - } - - std::set remaps; - remaps.insert(property->_setter_remaps.begin(), - property->_setter_remaps.end()); - - // We have to create an args tuple only to unpack it later, ugh. - out << " PyObject *args = PyTuple_New(2);\n" - << " PyTuple_SET_ITEM(args, 0, Py_NewRef(key));\n" - << " PyTuple_SET_ITEM(args, 1, Py_NewRef(value));\n"; - - string expected_params; - if (!write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_varargs, - RF_int | RF_decref_args, false, false)) { - error_bad_args_return(out, 2, RF_int | RF_decref_args, expected_params); - } - out << "}\n\n"; - } - - if (property->_getkey_function != nullptr) { - out << - "/**\n" - " * mapping key-getter for property " << ielem.get_scoped_name() << "\n" - " */\n" - "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Mapping_Getkey(PyObject *self, Py_ssize_t index) {\n"; - - if (property->_has_this) { - out << - " " << cClassName << " *local_this = nullptr;\n" - " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n" - " return nullptr;\n" - " }\n"; - } - - // We need to raise IndexError if we're out of bounds. - if (len_remap != nullptr) { - out << " if (index < 0 || index >= (Py_ssize_t)" - << len_remap->get_call_str("local_this", pexprs) << ") {\n"; - out << "#ifdef NDEBUG\n"; - out << " PyErr_SetString(PyExc_IndexError, \"index out of range\");\n"; - out << "#else\n"; - out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n"; - out << "#endif\n"; - out << " return nullptr;\n"; - out << " }\n"; - } - - std::set remaps; - - // Extract only the getters that take one integral argument. - for (FunctionRemap *remap : property->_getkey_function->_remaps) { - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (min_num_args <= 1 && max_num_args >= 1 && - TypeManager::is_integer(remap->_parameters[(size_t)remap->_has_this]._remap->get_new_type())) { - remaps.insert(remap); - } - } - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { - error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); - } - out << "}\n\n"; - } - } - - // Now write the actual getter wrapper. It will be a different wrapper - // depending on whether it's a mapping or a sequence. - out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n"; - - // Is this property shadowing a static method with the same name? This is a - // special case to handle WindowProperties::make -- see GH #444. - if (property->_has_this) { - for (const Function *func : obj->_methods) { - if (!func->_has_this && func->_ifunc.get_name() == ielem.get_name()) { - string flags; - string fptr = "&" + func->_name; - switch (func->_args_type) { - case AT_keyword_args: - flags = "METH_VARARGS | METH_KEYWORDS"; - fptr = "(PyCFunction) " + fptr; - break; - case AT_varargs: - flags = "METH_VARARGS"; - break; - case AT_single_arg: - flags = "METH_O"; - break; - default: - flags = "METH_NOARGS"; - break; - } - out << " if (self == nullptr) {\n" - << " static PyMethodDef def = {\"" << ielem.get_name() << "\", " - << fptr << ", " << flags << " | METH_STATIC, (const char *)" - << func->_name << "_comment};\n" - << " return PyCFunction_New(&def, nullptr);\n" - << " }\n\n"; - break; - } - } - } - - if (ielem.is_mapping()) { - if (property->_has_this) { - out << " nassertr(self != nullptr, nullptr);\n"; - } - if (property->_setter_remaps.empty()) { - out << " Dtool_MappingWrapper *wrap = Dtool_NewMappingWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n"; - } else { - out << " Dtool_MappingWrapper *wrap = Dtool_NewMutableMappingWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n"; - } - out << " if (wrap != nullptr) {\n" - " wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n"; - if (!property->_setter_remaps.empty()) { - if (property->_has_this) { - out << " if (!DtoolInstance_IS_CONST(self)) {\n"; - } else { - out << " {\n"; - } - out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n"; - out << " }\n"; - } - if (property->_length_function != nullptr) { - out << " wrap->_keys._len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"; - if (property->_getkey_function != nullptr) { - out << " wrap->_keys._getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getkey;\n"; - } - } - out << " }\n" - " return (PyObject *)wrap;\n" - "}\n\n"; - - } else if (ielem.is_sequence()) { - if (property->_has_this) { - out << " nassertr(self != nullptr, nullptr);\n"; - } - if (property->_setter_remaps.empty()) { - out << - " Dtool_SequenceWrapper *wrap = Dtool_NewSequenceWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n" - " if (wrap != nullptr) {\n" - " wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n" - " wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n"; - } else { - out << - " Dtool_MutableSequenceWrapper *wrap = Dtool_NewMutableSequenceWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n" - " if (wrap != nullptr) {\n" - " wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n" - " wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n"; - if (!property->_setter_remaps.empty()) { - if (property->_has_this) { - out << " if (!DtoolInstance_IS_CONST(self)) {\n"; - } else { - out << " {\n"; - } - out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n"; - if (property->_inserter != nullptr) { - out << " wrap->_insert_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_insert;\n"; - } - out << " }\n"; - } - } - out << " }\n" - " return (PyObject *)wrap;\n" - "}\n\n"; - - } else { - // Write out a regular, unwrapped getter. - FunctionRemap *remap = property->_getter_remaps.front(); - - if (remap->_has_this) { - if (remap->_const_method) { - out << " const " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; - } else { - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" - << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; - } - out << " return nullptr;\n"; - out << " }\n\n"; - } - - if (property->_has_function != nullptr) { - if (remap->_has_this) { - out << " if (!local_this->" << property->_has_function->_ifunc.get_name() << "()) {\n"; - } else { - out << " if (!" << cClassName << "::" << property->_has_function->_ifunc.get_name() << "()) {\n"; - } - out << " return Py_NewRef(Py_None);\n" - << " }\n"; - } - - std::set remaps; - remaps.insert(remap); - - string expected_params; - write_function_forset(out, remaps, 0, 0, - expected_params, 2, false, true, AT_no_args, - RF_pyobject | RF_err_null, false, false); - out << "}\n\n"; - - // Write out a setter if this is not a read-only property. - if (!property->_setter_remaps.empty()) { - out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n"; - if (remap->_has_this) { - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \"" - << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n"; - out << " return -1;\n"; - out << " }\n\n"; - } - - out << " if (arg == nullptr) {\n"; - if (property->_deleter != nullptr && remap->_has_this) { - out << " local_this->" << property->_deleter->_ifunc.get_name() << "();\n" - << " return 0;\n"; - } else if (property->_deleter != nullptr) { - out << " " << cClassName << "::" << property->_deleter->_ifunc.get_name() << "();\n" - << " return 0;\n"; - } else { - out << "#ifdef NDEBUG\n" - " Dtool_Raise_TypeError(\"can't delete attribute\");\n" - "#else\n" - " Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << " attribute\");\n" - "#endif\n" - " return -1;\n"; - } - out << " }\n"; - - if (property->_clear_function != nullptr) { - out << " if (arg == Py_None) {\n"; - if (remap->_has_this) { - out << " local_this->" << property->_clear_function->_ifunc.get_name() << "();\n"; - } else { - out << " " << cClassName << "::" << property->_clear_function->_ifunc.get_name() << "();\n"; - } - out << " return 0;\n" - << " }\n"; - } - - std::set remaps; - - // Extract only the setters that take one argument. - for (FunctionRemap *remap : property->_setter_remaps) { - int min_num_args = remap->get_min_num_args(); - int max_num_args = remap->get_max_num_args(); - if (min_num_args <= 1 && max_num_args >= 1) { - remaps.insert(remap); - } - } - - string expected_params; - if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, - true, AT_single_arg, RF_int, false, false)) { - error_bad_args_return(out, 2, RF_int, expected_params); - } - out << "}\n\n"; - } - } -} - -/** - * Records the indicated type, which may be a struct type, along with all of - * its associated methods, if any. - */ -InterfaceMaker::Object *InterfaceMakerPythonNative:: -record_object(TypeIndex type_index) { - if (type_index == 0) { - return nullptr; - } - - Objects::iterator oi = _objects.find(type_index); - if (oi != _objects.end()) { - return (*oi).second; - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateType &itype = idb->get_type(type_index); - - if (!is_cpp_type_legal(itype._cpptype)) { - return nullptr; - } - - Object *object = new Object(itype); - bool inserted = _objects.insert(Objects::value_type(type_index, object)).second; - assert(inserted); - - Function *function; - - int num_constructors = itype.number_of_constructors(); - for (int ci = 0; ci < num_constructors; ci++) { - function = record_function(itype, itype.get_constructor(ci)); - if (is_function_legal(function)) { - object->_constructors.push_back(function); - } - } - - int num_methods = itype.number_of_methods(); - int mi; - for (mi = 0; mi < num_methods; mi++) { - function = record_function(itype, itype.get_method(mi)); - if (is_function_legal(function)) { - object->_methods.push_back(function); - } - } - - int num_casts = itype.number_of_casts(); - for (mi = 0; mi < num_casts; mi++) { - function = record_function(itype, itype.get_cast(mi)); - if (is_function_legal(function)) { - object->_methods.push_back(function); - } - } - - int num_derivations = itype.number_of_derivations(); - for (int di = 0; di < num_derivations; di++) { - TypeIndex d_type_Index = itype.get_derivation(di); - idb->get_type(d_type_Index); - - if (!interrogate_type_is_unpublished(d_type_Index)) { - if (itype.derivation_has_upcast(di)) { - function = record_function(itype, itype.derivation_get_upcast(di)); - if (is_function_legal(function)) { - object->_methods.push_back(function); - } - } - /*if (itype.derivation_has_downcast(di)) { - // Downcasts are methods of the base class, not the child class. - TypeIndex base_type_index = itype.get_derivation(di); - - const InterrogateType &base_type = idb->get_type(base_type_index); - function = record_function(base_type, itype.derivation_get_downcast(di)); - - if (is_function_legal(function)) { - Object *pobject = record_object(base_type_index); - if (pobject != NULL) { - pobject->_methods.push_back(function); - } - } - }*/ - } - } - - int num_elements = itype.number_of_elements(); - for (int ei = 0; ei < num_elements; ei++) { - ElementIndex element_index = itype.get_element(ei); - - Property *property = record_property(itype, element_index); - if (property != nullptr) { - object->_properties.push_back(property); - } else { - // No use exporting a property without a getter. - delete property; - } - } - - int num_make_seqs = itype.number_of_make_seqs(); - for (int msi = 0; msi < num_make_seqs; msi++) { - MakeSeqIndex make_seq_index = itype.get_make_seq(msi); - const InterrogateMakeSeq &imake_seq = idb->get_make_seq(make_seq_index); - - string class_name = itype.get_scoped_name(); - string clean_name = InterrogateBuilder::clean_identifier(class_name); - string wrapper_name = "MakeSeq_" + clean_name + "_" + imake_seq.get_name(); - - MakeSeq *make_seq = new MakeSeq(wrapper_name, imake_seq); - make_seq->_length_getter = record_function(itype, imake_seq.get_length_getter()); - make_seq->_element_getter = record_function(itype, imake_seq.get_element_getter()); - object->_make_seqs.push_back(make_seq); - } - - object->check_protocols(); - - int num_nested = itype.number_of_nested_types(); - for (int ni = 0; ni < num_nested; ni++) { - TypeIndex nested_index = itype.get_nested_type(ni); - record_object(nested_index); - } - return object; -} - -/** - * - */ -InterfaceMaker::Property *InterfaceMakerPythonNative:: -record_property(const InterrogateType &itype, ElementIndex element_index) { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - const InterrogateElement &ielement = idb->get_element(element_index); - if (!ielement.has_getter()) { - // A property needs at the very least a getter. - return nullptr; - } - - Property *property; - { - FunctionIndex func_index = ielement.get_getter(); - if (func_index != 0) { - const InterrogateFunction &ifunc = idb->get_function(func_index); - property = new Property(ielement); - - InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); ii != ifunc._instances->end(); ++ii) { - CPPInstance *cppfunc = (*ii).second; - FunctionRemap *remap = - make_function_remap(itype, ifunc, cppfunc, 0); - - if (remap != nullptr && is_remap_legal(remap)) { - property->_getter_remaps.push_back(remap); - property->_has_this |= remap->_has_this; - } - } - } else { - return nullptr; - } - } - - if (ielement.has_setter()) { - FunctionIndex func_index = ielement.get_setter(); - if (func_index != 0) { - const InterrogateFunction &ifunc = idb->get_function(func_index); - - InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); ii != ifunc._instances->end(); ++ii) { - CPPInstance *cppfunc = (*ii).second; - FunctionRemap *remap = - make_function_remap(itype, ifunc, cppfunc, 0); - - if (remap != nullptr && is_remap_legal(remap)) { - property->_setter_remaps.push_back(remap); - property->_has_this |= remap->_has_this; - } - } - } - } - - if (ielement.has_has_function()) { - FunctionIndex func_index = ielement.get_has_function(); - Function *has_function = record_function(itype, func_index); - if (is_function_legal(has_function)) { - property->_has_function = has_function; - property->_has_this |= has_function->_has_this; - } - } - - if (ielement.has_clear_function()) { - FunctionIndex func_index = ielement.get_clear_function(); - Function *clear_function = record_function(itype, func_index); - if (is_function_legal(clear_function)) { - property->_clear_function = clear_function; - property->_has_this |= clear_function->_has_this; - } - } - - if (ielement.has_del_function()) { - FunctionIndex func_index = ielement.get_del_function(); - Function *del_function = record_function(itype, func_index); - if (is_function_legal(del_function)) { - property->_deleter = del_function; - property->_has_this |= del_function->_has_this; - } - } - - if (ielement.is_sequence() || ielement.is_mapping()) { - FunctionIndex func_index = ielement.get_length_function(); - if (func_index != 0) { - property->_length_function = record_function(itype, func_index); - } - } - - if (ielement.is_sequence() && ielement.has_insert_function()) { - FunctionIndex func_index = ielement.get_insert_function(); - Function *insert_function = record_function(itype, func_index); - if (is_function_legal(insert_function)) { - property->_inserter = insert_function; - property->_has_this |= insert_function->_has_this; - } - } - - if (ielement.is_mapping() && ielement.has_getkey_function()) { - FunctionIndex func_index = ielement.get_getkey_function(); - assert(func_index != 0); - Function *getkey_function = record_function(itype, func_index); - if (is_function_legal(getkey_function)) { - property->_getkey_function = getkey_function; - property->_has_this |= getkey_function->_has_this; - } - } - - return property; -} - -/** - * Walks through the set of functions in the database and generates wrappers - * for each function, storing these in the database. No actual code should be - * output yet; this just updates the database with the wrapper information. - */ -void InterfaceMakerPythonNative:: -generate_wrappers() { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - // We use a while loop rather than a simple for loop, because we might - // increase the number of types recursively during the traversal. - - int ti = 0; - while (ti < idb->get_num_all_types()) { - TypeIndex type_index = idb->get_all_type(ti); - record_object(type_index); - ++ti; - } - - int num_global_elements = idb->get_num_global_elements(); - for (int gi = 0; gi < num_global_elements; ++gi) { - TypeIndex type_index = idb->get_global_element(gi); - record_object(type_index); - } - - int num_functions = idb->get_num_global_functions(); - for (int fi = 0; fi < num_functions; fi++) { - FunctionIndex func_index = idb->get_global_function(fi); - record_function(dummy_type, func_index); - } - - int num_manifests = idb->get_num_global_manifests(); - for (int mi = 0; mi < num_manifests; mi++) { - ManifestIndex manifest_index = idb->get_global_manifest(mi); - const InterrogateManifest &iman = idb->get_manifest(manifest_index); - if (iman.has_getter()) { - FunctionIndex func_index = iman.get_getter(); - record_function(dummy_type, func_index); - } - } - - int num_elements = idb->get_num_global_elements(); - for (int ei = 0; ei < num_elements; ei++) { - ElementIndex element_index = idb->get_global_element(ei); - const InterrogateElement &ielement = idb->get_element(element_index); - if (ielement.has_getter()) { - FunctionIndex func_index = ielement.get_getter(); - record_function(dummy_type, func_index); - } - if (ielement.has_setter()) { - FunctionIndex func_index = ielement.get_setter(); - record_function(dummy_type, func_index); - } - } -} - -/** - - */ -bool InterfaceMakerPythonNative:: -is_cpp_type_legal(CPPType *in_ctype) { - if (in_ctype == nullptr) { - return false; - } - - string name = in_ctype->get_local_name(&parser); - - if (builder.in_ignoretype(name)) { - return false; - } - - if (builder.in_forcetype(name)) { - return true; - } - - // bool answer = false; - CPPType *type = TypeManager::resolve_type(in_ctype); - if (TypeManager::is_rvalue_reference(type)) { - return false; - } - - type = TypeManager::unwrap(type); - - if (TypeManager::is_void(type)) { - return true; - } else if (TypeManager::is_basic_string_char(type)) { - return true; - } else if (TypeManager::is_basic_string_wchar(type)) { - return true; - } else if (TypeManager::is_vector_unsigned_char(in_ctype)) { - return true; - } else if (TypeManager::is_simple(type)) { - return true; - } else if (TypeManager::is_pointer_to_simple(type)) { - return true; - } else if (builder.in_forcetype(type->get_local_name(&parser))) { - return true; - } else if (TypeManager::is_exported(type)) { - return true; - } else if (TypeManager::is_pointer_to_PyObject(in_ctype)) { - return true; - } else if (TypeManager::is_pointer_to_Py_buffer(in_ctype)) { - return true; - } - - // if (answer == false) printf(" -------------------- Bad Type ?? - // %s\n",type->get_local_name().c_str()); - - return false; -} -/** - - */ -bool InterfaceMakerPythonNative:: -isExportThisRun(CPPType *ctype) { - if (builder.in_forcetype(ctype->get_local_name(&parser))) { - return true; - } - - if (!TypeManager::is_exported(ctype)) { - return false; - } - - if (TypeManager::is_local(ctype)) { - return true; - } - - return false; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -isExportThisRun(Function *func) { - if (func == nullptr || !is_function_legal(func)) { - return false; - } - - for (FunctionRemap *remap : func->_remaps) { - return isExportThisRun(remap->_cpptype); - } - - return false; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -is_remap_legal(FunctionRemap *remap) { - if (remap == nullptr) { - return false; - } - - // return must be legal and managable.. - if (!is_cpp_type_legal(remap->_return_type->get_orig_type())) { -// printf(" is_remap_legal Return Is Bad %s\n",remap->_return_type->get_orig_ -// type()->get_fully_scoped_name().c_str()); - // Except if this is a spaceship operator, since we have special handling - // for its return type. - if (remap->_cppfunc->get_simple_name() != "operator <=>") { - return false; - } - } - - // We don't currently support returning pointers, but we accept them as - // function parameters. But const char * is an exception. - if (!remap->_return_type->new_type_is_atomic_string() && - TypeManager::is_pointer_to_simple(remap->_return_type->get_orig_type())) { - return false; - } - - // ouch .. bad things will happen here .. do not even try.. - if (remap->_ForcedVoidReturn) { - return false; - } - - // all non-optional params must be legal - for (size_t pn = 0; pn < remap->_parameters.size(); pn++) { - ParameterRemap *param = remap->_parameters[pn]._remap; - CPPType *orig_type = param->get_orig_type(); - if (param->get_default_value() == nullptr && !is_cpp_type_legal(orig_type)) { - return false; - } - } - - // Don't export global operators. - if (!remap->_has_this && - remap->_cppfunc->get_simple_name().compare(0, 9, "operator ") == 0) { - return false; - } - - // ok all looks ok. - return true; -} - -/** - - */ -int InterfaceMakerPythonNative:: -has_coerce_constructor(CPPStructType *type) { - if (type == nullptr) { - return 0; - } - - // It is convenient to set default-constructability and move-assignability - // as requirement for non-reference-counted objects, since it simplifies the - // implementation and it holds for all classes we need it for. - if (!TypeManager::is_reference_count(type) && - (!type->is_default_constructible() || !type->is_move_assignable())) { - return 0; - } - - CPPScope *scope = type->get_scope(); - if (scope == nullptr) { - return 0; - } - - int result = 0; - - CPPScope::Functions::iterator fgi; - for (fgi = scope->_functions.begin(); fgi != scope->_functions.end(); ++fgi) { - CPPFunctionGroup *fgroup = fgi->second; - for (CPPInstance *inst : fgroup->_instances) { - CPPFunctionType *ftype = inst->_type->as_function_type(); - if (ftype == nullptr) { - continue; - } - if (inst->_storage_class & CPPInstance::SC_explicit) { - // Skip it if it is marked not to allow coercion. - continue; - } - - if (inst->_vis > min_vis) { - // Not published. - continue; - } - - CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters; - if (params.size() == 0) { - // It's useless if it doesn't take any parameters. - continue; - } - - if (ftype->_flags & CPPFunctionType::F_constructor) { - if (ftype->_flags & (CPPFunctionType::F_copy_constructor | - CPPFunctionType::F_move_constructor)) { - // Skip a copy and move constructor. - continue; - } else { - return 2; - } - - } else if (fgroup->_name == "make" && (inst->_storage_class & CPPInstance::SC_static) != 0) { - if (TypeManager::is_const_pointer_or_ref(ftype->_return_type)) { - result = 1; - } else { - return 2; - } - } - } - } - - return result; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -is_remap_coercion_possible(FunctionRemap *remap) { - if (remap == nullptr) { - return false; - } - - size_t pn = 0; - if (remap->_has_this) { - // Skip the "this" parameter. It's never coercible. - ++pn; - } - while (pn < remap->_parameters.size()) { - CPPType *type = remap->_parameters[pn]._remap->get_new_type(); - - if (TypeManager::is_char_pointer(type)) { - } else if (TypeManager::is_wchar_pointer(type)) { - } else if (TypeManager::is_pointer_to_PyObject(type)) { - } else if (TypeManager::is_pointer_to_Py_buffer(type)) { - } else if (TypeManager::is_pointer_to_simple(type)) { - } else if (TypeManager::is_pointer(type)) { - // This is a pointer to an object, so we might be able to coerce a - // parameter to it. - CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(type)); - if (has_coerce_constructor(obj_type->as_struct_type()) > 0) { - // It has a coercion constructor, so go for it. - return true; - } - } - ++pn; - } - - return false; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -is_function_legal(Function *func) { - for (FunctionRemap *remap : func->_remaps) { - if (is_remap_legal(remap)) { -// printf(" Function Is Marked Legal %s\n",func->_name.c_str()); - - return true; - } - } - -// printf(" Function Is Marked Illegal %s\n",func->_name.c_str()); - return false; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -IsRunTimeTyped(const InterrogateType &itype) { - TypeIndex ptype_id = itype.get_outer_class(); - if (ptype_id > 0) { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - InterrogateType ptype = idb->get_type(ptype_id); - return IsRunTimeTyped(ptype); - } - - if (itype.get_name() == "TypedObject") { - return true; - } - - return false; -} - -/** - * Returns true if this object has special support for inheriting from Python. - */ -bool InterfaceMakerPythonNative:: -is_python_subclassable(CPPStructType *struct_type) { - if (struct_type != nullptr && !struct_type->is_final() && - IsPandaTypedObject(struct_type) && - TypeManager::is_reference_count(struct_type)) { - - // Make sure the type has a published constructor. - TypeIndex type_index = builder.get_type(struct_type, false); - if (type_index != 0) { - Objects::iterator oi = _objects.find(type_index); - if (oi != _objects.end()) { - Object *obj = (*oi).second; - return !obj->_constructors.empty(); - } - } - } - return false; -} - -/** - * Returns true if the type has a public member named __self__. - */ -bool InterfaceMakerPythonNative:: -has_self_member(CPPStructType *struct_type) { - if (struct_type == nullptr) { - return false; - } - - CPPScope *scope = struct_type->get_scope(); - if (scope != nullptr && scope->_variables.count("__self__")) { - return true; - } - - for (const CPPStructType::Base &base : struct_type->_derivation) { - if (base._base != nullptr) { - CPPStructType *base_type = base._base->as_struct_type(); - if (base_type != nullptr && has_self_member(base_type)) { - return true; - } - } - } - return false; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -DoesInheritFromIsClass(const CPPStructType *inclass, const std::string &name) { - if (inclass == nullptr) { - return false; - } - - std::string scoped_name = inclass->get_fully_scoped_name(); - if (scoped_name == name) { - return true; - } - - for (const CPPStructType::Base &base : inclass->_derivation) { - CPPStructType *base_type = TypeManager::resolve_type(base._base)->as_struct_type(); - if (base_type != nullptr) { - if (DoesInheritFromIsClass(base_type, name)) { - return true; - } - } - } - return false; -} - -/** - - */ -bool InterfaceMakerPythonNative:: -has_get_class_type_function(CPPType *type) { - while (type->get_subtype() == CPPDeclaration::ST_typedef) { - type = type->as_typedef_type()->_type; - } - - CPPStructType *struct_type = type->as_struct_type(); - if (struct_type == nullptr) { - return false; - } - - CPPScope *scope = struct_type->get_scope(); - - return scope->_functions.find("get_class_type") != scope->_functions.end(); -} - -/** - * - */ -bool InterfaceMakerPythonNative:: -has_init_type_function(CPPType *type) { - while (type->get_subtype() == CPPDeclaration::ST_typedef) { - type = type->as_typedef_type()->_type; - } - - CPPStructType *struct_type = type->as_struct_type(); - if (struct_type == nullptr) { - return false; - } - - CPPScope *scope = struct_type->get_scope(); - CPPScope::Functions::const_iterator it = scope->_functions.find("init_type"); - if (it == scope->_functions.end()) { - return false; - } - const CPPFunctionGroup *group = it->second; - - for (const CPPInstance *cppinst : group->_instances) { - const CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); - - if (cppfunc != nullptr && - cppfunc->_parameters != nullptr && - cppfunc->_parameters->_parameters.size() == 0 && - (cppinst->_storage_class & CPPInstance::SC_static) != 0) { - return true; - } - } - - return false; -} - -/** - * Returns -1 if the class does not define write() (and therefore cannot - * support a __str__ function). - * - * Returns 1 if the class defines write(ostream). - * - * Returns 2 if the class defines write(ostream, int). - * - * Note that if you want specific behavior for Python str(), you should just - * define a __str__ function, which maps directly to the appropriate type - * slot. - */ -int InterfaceMakerPythonNative:: -NeedsAStrFunction(const InterrogateType &itype_class) { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - int num_methods = itype_class.number_of_methods(); - int mi; - for (mi = 0; mi < num_methods; ++mi) { - FunctionIndex func_index = itype_class.get_method(mi); - const InterrogateFunction &ifunc = idb->get_function(func_index); - if (ifunc.get_name() == "write") { - if (ifunc._instances != nullptr) { - InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); - ii != ifunc._instances->end(); - ++ii) { - CPPInstance *cppinst = (*ii).second; - CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); - - if (cppfunc != nullptr) { - if (cppfunc->_parameters != nullptr && - cppfunc->_return_type != nullptr && - TypeManager::is_void(cppfunc->_return_type)) { - if (cppfunc->_parameters->_parameters.size() == 1) { - CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; - if (TypeManager::is_pointer_to_ostream(inst1->_type)) { - // write(ostream) - return 1; - } - } - - if (cppfunc->_parameters->_parameters.size() == 2) { - CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; - if (TypeManager::is_pointer_to_ostream(inst1->_type)) { - inst1 = cppfunc->_parameters->_parameters[1]; - if (inst1->_initializer != nullptr) { - // write(ostream, int = 0) - return 1; - } - - if (TypeManager::is_integer(inst1->_type)) { - // write(ostream, int) - return 2; - } - } - } - } - } - } - } - } - } - - return -1; -} - -/** - * Returns -1 if the class does not define output() or python_repr() (and - * therefore cannot support a __repr__ function). - * - * Returns 1 if the class defines python_repr(ostream, string). - * - * Returns 2 if the class defines output(ostream). - * - * Returns 3 if the class defines an extension function for - * python_repr(ostream, string). - * - * Note that defining python_repr is deprecated in favor of defining a - * __repr__ that returns a string, which maps directly to the appropriate type - * slot. - */ -int InterfaceMakerPythonNative:: -NeedsAReprFunction(const InterrogateType &itype_class) { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - int num_methods = itype_class.number_of_methods(); - int mi; - for (mi = 0; mi < num_methods; ++mi) { - FunctionIndex func_index = itype_class.get_method(mi); - const InterrogateFunction &ifunc = idb->get_function(func_index); - if (ifunc.get_name() == "python_repr") { - if (ifunc._instances != nullptr) { - InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); - ii != ifunc._instances->end(); - ++ii) { - CPPInstance *cppinst = (*ii).second; - CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); - - if (cppfunc != nullptr) { - if (cppfunc->_parameters != nullptr && - cppfunc->_return_type != nullptr && - TypeManager::is_void(cppfunc->_return_type)) { - if (cppfunc->_parameters->_parameters.size() == 2) { - CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; - if (TypeManager::is_pointer_to_ostream(inst1->_type)) { - inst1 = cppfunc->_parameters->_parameters[1]; - if (TypeManager::is_string(inst1->_type) || - TypeManager::is_char_pointer(inst1->_type)) { - // python_repr(ostream, string) - if ((cppinst->_storage_class & CPPInstance::SC_extension) != 0) { - return 3; - } else { - return 1; - } - } - } - } - } - } - } - } - } - } - - for (mi = 0; mi < num_methods; ++mi) { - FunctionIndex func_index = itype_class.get_method(mi); - const InterrogateFunction &ifunc = idb->get_function(func_index); - if (ifunc.get_name() == "output") { - if (ifunc._instances != nullptr) { - InterrogateFunction::Instances::const_iterator ii; - for (ii = ifunc._instances->begin(); - ii != ifunc._instances->end(); - ++ii) { - CPPInstance *cppinst = (*ii).second; - CPPFunctionType *cppfunc = cppinst->_type->as_function_type(); - - if (cppfunc != nullptr) { - if (cppfunc->_parameters != nullptr && - cppfunc->_return_type != nullptr && - TypeManager::is_void(cppfunc->_return_type)) { - if (cppfunc->_parameters->_parameters.size() == 1) { - CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; - if (TypeManager::is_pointer_to_ostream(inst1->_type)) { - // output(ostream) - return 2; - } - } - - if (cppfunc->_parameters->_parameters.size() >= 2) { - CPPInstance *inst1 = cppfunc->_parameters->_parameters[0]; - if (TypeManager::is_pointer_to_ostream(inst1->_type)) { - inst1 = cppfunc->_parameters->_parameters[1]; - if (inst1->_initializer != nullptr) { - // output(ostream, foo = bar, ...) - return 2; - } - } - } - } - } - } - } - } - } - - return -1; -} - -/** - * Returns true if the class defines a rich comparison operator. - */ -bool InterfaceMakerPythonNative:: -NeedsARichCompareFunction(const InterrogateType &itype_class) { - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - int num_methods = itype_class.number_of_methods(); - int mi; - for (mi = 0; mi < num_methods; ++mi) { - FunctionIndex func_index = itype_class.get_method(mi); - const InterrogateFunction &ifunc = idb->get_function(func_index); - if (ifunc.get_name() == "operator <") { - return true; - } - if (ifunc.get_name() == "operator <=") { - return true; - } - if (ifunc.get_name() == "operator ==") { - return true; - } - if (ifunc.get_name() == "operator !=") { - return true; - } - if (ifunc.get_name() == "operator >") { - return true; - } - if (ifunc.get_name() == "operator >=") { - return true; - } - } - - if (itype_class._cpptype != nullptr) { - CPPStructType *struct_type = itype_class._cpptype->as_struct_type(); - if (struct_type != nullptr) { - CPPScope *scope = struct_type->get_scope(); - CPPScope::Functions::const_iterator it = scope->_functions.find("operator <=>"); - if (it != scope->_functions.end()) { - return true; - } - } - } - - return false; -} - -/** - * Outputs the indicated string as a single quoted, multi-line string to the - * generated C++ source code. The output point is left on the last line of - * the string, following the trailing quotation mark. - */ -void InterfaceMakerPythonNative:: -output_quoted(ostream &out, int indent_level, const std::string &str, - bool first_line) { - indent(out, (first_line ? indent_level : 0)) - << '"'; - std::string::const_iterator si; - for (si = str.begin(); si != str.end();) { - switch (*si) { - case '"': - case '\\': - out << '\\' << *si; - break; - - case '\n': - out << "\\n\""; - if (++si == str.end()) { - return; - } - out << "\n"; - indent(out, indent_level) - << '"'; - continue; - - case '\t': - out << "\\t"; - break; - - default: - if (!isprint(*si)) { - out << "\\" << oct << std::setw(3) << std::setfill('0') << (unsigned int)(*si) - << dec; - } else { - out << *si; - } - } - ++si; - } - out << '"'; -} diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h deleted file mode 100644 index aec04a6652..0000000000 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ /dev/null @@ -1,232 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPythonNative.h - */ - -#ifndef INTERFACEMAKERPYTHONNATIVE_H -#define INTERFACEMAKERPYTHONNATIVE_H -#include -#include -#include "dtoolbase.h" - -#include "interfaceMakerPython.h" -#include "interrogate_interface.h" -#include "cppStructType.h" - -class FunctionRemap; - -/** - * An InterfaceMaker for generating complex Python function wrappers around - * C++ code. - */ -class InterfaceMakerPythonNative : public InterfaceMakerPython { -public: - InterfaceMakerPythonNative(InterrogateModuleDef *def); - virtual ~InterfaceMakerPythonNative(); - - - virtual void write_prototypes(std::ostream &out, std::ostream *out_h); - void write_prototypes_class(std::ostream &out, std::ostream *out_h, Object *obj) ; - void write_prototypes_class_external(std::ostream &out, Object *obj); - - virtual void write_functions(std::ostream &out); - - virtual void write_module(std::ostream &out, std::ostream *out_h, InterrogateModuleDef *def); - virtual void write_module_support(std::ostream &out, std::ostream *out_h, InterrogateModuleDef *def); - - void write_module_class(std::ostream &out, Object *cls); - virtual void write_sub_module(std::ostream &out, Object *obj); - - virtual bool synthesize_this_parameter(); - virtual bool separate_overloading(); - - virtual Object *record_object(TypeIndex type_index); - Property *record_property(const InterrogateType &itype, ElementIndex element_index); - -protected: - virtual std::string get_wrapper_prefix(); - virtual std::string get_unique_prefix(); - virtual void record_function_wrapper(InterrogateFunction &ifunc, - FunctionWrapperIndex wrapper_index); - - virtual void generate_wrappers(); - -private: - // This enum defines the various prototypes that must be generated for the - // specialty functions that Python requires, especially for the slotted - // functions. - enum WrapperType { - WT_none, - WT_no_params, - WT_one_param, - WT_binary_operator, - WT_setattr, - WT_getattr, - WT_sequence_getitem, - WT_sequence_setitem, - WT_sequence_size, - WT_mapping_setitem, - WT_inquiry, - WT_getbuffer, - WT_releasebuffer, - WT_iter_next, - WT_ternary_operator, - WT_inplace_binary_operator, - WT_inplace_ternary_operator, - WT_traverse, - WT_compare, - WT_hash, - WT_new, - }; - - // This enum is passed to the wrapper generation functions to indicate what - // sort of values the wrapper function is expected to return. - enum ReturnFlags { - // -1 on failure, 0 on success. - RF_int = 0x100, - - // Like RF_int, but special case that it returns -1, 0, or 1. - RF_compare = RF_int | 0x200, - - // Returns the actual return value as PyObject*. - RF_pyobject = 0x010, - - // Returns a reference to self. - RF_self = 0x020, - - // Assign to the coerced argument, in the case of a coercion constructor. - RF_coerced = 0x040, - - // Don't automatically map NULL to None - RF_preserve_null = 0x080, - - // These indicate what should be returned on error. - RF_err_notimplemented = 0x002, - RF_err_null = 0x004, - RF_err_false = 0x008, - - // Decref temporary args object before returning. - RF_decref_args = 0x1000, - - // This raises a KeyError on falsey (or -1) return value. - RF_raise_keyerror = 0x4000, - - // Invert boolean return value. - RF_invert_bool = 0x8000, - - // Used inside a rich comparison function. - RF_richcompare_zero = 0x10000, - }; - - class SlottedFunctionDef { - public: - std::string _answer_location; - WrapperType _wrapper_type; - int _min_version = 0; - std::string _wrapper_name; - std::set _remaps; - bool _keep_method; - }; - - typedef std::map SlottedFunctions; - - static bool get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, SlottedFunctionDef &def); - static void write_function_slot(std::ostream &out, int indent_level, - const SlottedFunctions &slots, - const std::string &slot, const std::string &def = "nullptr"); - - void write_prototype_for_name(std::ostream &out, Function *func, const std::string &name); - void write_prototype_for(std::ostream &out, Function *func); - void write_function_for_top(std::ostream &out, Object *obj, Function *func); - - void write_function_for_name(std::ostream &out, Object *obj, - const Function::Remaps &remaps, - const std::string &name, std::string &expected_params, - bool coercion_allowed, - ArgsType args_type, int return_flags); - void write_coerce_constructor(std::ostream &out, Object *obj, bool is_const); - - int collapse_default_remaps(std::map > &map_sets, - int max_required_args); - - bool write_function_forset(std::ostream &out, - const std::set &remaps, - int min_num_args, int max_num_args, - std::string &expected_params, int indent_level, - bool coercion_allowed, bool report_errors, - ArgsType args_type, int return_flags, - bool check_exceptions = true, - bool verify_const = true, - const std::string &first_expr = std::string()); - - bool write_function_instance(std::ostream &out, FunctionRemap *remap, - int min_num_args, int max_num_args, - std::string &expected_params, int indent_level, - bool coercion_allowed, bool report_errors, - ArgsType args_type, int return_flags, - bool check_exceptions = true, - const std::string &first_pexpr = std::string()); - - void error_return(std::ostream &out, int indent_level, int return_flags); - void error_bad_args_return(std::ostream &out, int indent_level, int return_flags, - const std::string &expected_params); - void error_raise_return(std::ostream &out, int indent_level, int return_flags, - const std::string &exc_type, const std::string &message, - const std::string &format_args = ""); - void pack_return_value(std::ostream &out, int indent_level, FunctionRemap *remap, - std::string return_expr, int return_flags); - - void write_make_seq(std::ostream &out, Object *obj, const std::string &ClassName, - const std::string &cClassName, MakeSeq *make_seq); - void write_getset(std::ostream &out, Object *obj, Property *property); - - void write_class_prototypes(std::ostream &out) ; - void write_class_declarations(std::ostream &out, std::ostream *out_h, Object *obj); - void write_class_details(std::ostream &out, Object *obj); - -public: - bool is_remap_legal(FunctionRemap *remap); - int has_coerce_constructor(CPPStructType *type); - bool is_remap_coercion_possible(FunctionRemap *remap); - bool is_function_legal(Function *func); - bool is_cpp_type_legal(CPPType *ctype); - bool isExportThisRun(CPPType *ctype); - bool isExportThisRun(Function *func); - bool isFunctionWithThis( Function *func); - bool IsRunTimeTyped(const InterrogateType &itype); - bool is_python_subclassable(CPPStructType *type); - bool has_self_member(CPPStructType *type); - - // comunicates the cast capabilites among methods.. - struct CastDetails { - CPPStructType *_structType; - std::string _to_class_name; - std::string _up_cast_string; - bool _can_downcast; - bool _is_legal_py_class; - }; - - void get_valid_child_classes(std::map &answer, CPPStructType *inclass, const std::string &upcast_seed = "", bool can_downcast = true); - bool DoesInheritFromIsClass(const CPPStructType * inclass, const std::string &name); - bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); }; - void write_python_instance(std::ostream &out, int indent_level, const std::string &return_expr, bool owns_memory, const InterrogateType &itype, bool is_const); - bool has_get_class_type_function(CPPType *type); - bool has_init_type_function(CPPType *type); - int NeedsAStrFunction(const InterrogateType &itype_class); - int NeedsAReprFunction(const InterrogateType &itype_class); - bool NeedsARichCompareFunction(const InterrogateType &itype_class); - - void output_quoted(std::ostream &out, int indent_level, const std::string &str, - bool first_line=true); - - // stash the forward declarations for this compile pass.. - std::set _external_imports; -}; - -#endif diff --git a/dtool/src/interrogate/interfaceMakerPythonObj.cxx b/dtool/src/interrogate/interfaceMakerPythonObj.cxx deleted file mode 100644 index 4182b0c9a1..0000000000 --- a/dtool/src/interrogate/interfaceMakerPythonObj.cxx +++ /dev/null @@ -1,658 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPythonObj.cxx - * @author drose - * @date 2001-09-19 - */ - -#include "interfaceMakerPythonObj.h" -#include "interrogateBuilder.h" -#include "interrogate.h" -#include "functionRemap.h" -#include "parameterRemapUnchanged.h" -#include "typeManager.h" -#include "functionWriterPtrFromPython.h" -#include "functionWriterPtrToPython.h" - -#include "interrogateDatabase.h" -#include "interrogateType.h" -#include "interrogateFunction.h" -#include "cppFunctionType.h" - -using std::ostream; -using std::string; - -/** - * - */ -InterfaceMakerPythonObj:: -InterfaceMakerPythonObj(InterrogateModuleDef *def) : - InterfaceMakerPython(def) -{ -} - -/** - * - */ -InterfaceMakerPythonObj:: -~InterfaceMakerPythonObj() { -} - -/** - * Generates the list of function prototypes corresponding to the functions - * that will be output in write_functions(). - */ -void InterfaceMakerPythonObj:: -write_prototypes(ostream &out, ostream *out_h) { - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - write_prototype_for(out, func); - } - - out << "\n"; - InterfaceMakerPython::write_prototypes(out,out_h); -} - -/** - * Generates the list of functions that are appropriate for this interface. - * This function is called *before* write_prototypes(), above. - */ -void InterfaceMakerPythonObj:: -write_functions(ostream &out) { - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - write_function_for(out, func); - } - - InterfaceMakerPython::write_functions(out); - - // Finally, generate all the make-class-wrapper functions. - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - - write_class_wrapper(out, object); - } -} - -/** - * Generates whatever additional code is required to support a module file. - */ -void InterfaceMakerPythonObj:: -write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) { - InterfaceMakerPython::write_module(out,out_h, def); - - out << "static PyMethodDef python_obj_funcs[] = {\n"; - - Objects::iterator oi; - for (oi = _objects.begin(); oi != _objects.end(); ++oi) { - Object *object = (*oi).second; - - Functions::iterator fi; - for (fi = object->_constructors.begin(); - fi != object->_constructors.end(); - ++fi) { - Function *func = (*fi); - out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name - << ", METH_VARARGS, nullptr },\n"; - } - } - out << " { nullptr, nullptr, 0, nullptr }\n" - << "};\n\n" - - << "#if PY_MAJOR_VERSION >= 3\n" - << "static struct PyModuleDef python_obj_module = {\n" - << " PyModuleDef_HEAD_INIT,\n" - << " \"" << def->library_name << "\",\n" - << " nullptr,\n" - << " -1,\n" - << " python_obj_funcs,\n" - << " nullptr, nullptr, nullptr, nullptr\n" - << "};\n\n" - - << "#define INIT_FUNC PyObject *PyInit_" << def->library_name << "\n" - << "#else\n" - << "#define INIT_FUNC void init" << def->library_name << "\n" - << "#endif\n\n" - - << "#ifdef _WIN32\n" - << "extern \"C\" __declspec(dllexport) INIT_FUNC();\n" - << "#elif __GNUC__ >= 4\n" - << "extern \"C\" __attribute__((visibility(\"default\"))) INIT_FUNC();\n" - << "#else\n" - << "extern \"C\" INIT_FUNC();\n" - << "#endif\n\n" - - << "INIT_FUNC() {\n" - << "#if PY_MAJOR_VERSION >= 3\n" - << " return PyModule_Create(&python_obj_module);\n" - << "#else\n" - << " Py_InitModule(\"" << def->library_name << "\", python_obj_funcs);\n" - << "#endif\n" - << "}\n\n"; -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require the implicit "this" parameter, if present, to be - * passed as the first parameter to any wrapper functions. - */ -bool InterfaceMakerPythonObj:: -synthesize_this_parameter() { - return true; -} - -/** - * Returns the name of the InterfaceMaker function generated to define the - * Python class for the indicated struct type. - */ -string InterfaceMakerPythonObj:: -get_builder_name(CPPType *struct_type) { - return "get_python_class_" + - InterrogateBuilder::clean_identifier(struct_type->get_local_name(&parser)); -} - -/** - * Returns the prefix string used to generate wrapper function names. - */ -string InterfaceMakerPythonObj:: -get_wrapper_prefix() { - return "wpo_"; -} - -/** - * Writes a function that will define the Python class. - */ -void InterfaceMakerPythonObj:: -write_class_wrapper(ostream &out, InterfaceMaker::Object *object) { - CPPType *struct_type = object->_itype._cpptype; - if (struct_type == nullptr) { - return; - } - - string name = get_builder_name(struct_type); - string python_name = - InterrogateBuilder::clean_identifier(struct_type->get_simple_name()); - - out << "/*\n" - << " * Generate unique Python class for " - << struct_type->get_local_name(&parser) << "\n" - << " */\n" - << "PyObject *\n" - << name << "() {\n" - << " static PyObject *wrapper = nullptr;\n" - << " static PyMethodDef methods[] = {\n"; - - int methods_size = 0; - int class_methods_size = 0; - - Functions::iterator fi; - for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) { - Function *func = (*fi); - if (func->_has_this) { - out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name - << ", METH_VARARGS },\n"; - methods_size++; - } - } - - out << " };\n" - << " static const int methods_size = " << methods_size << ";\n\n" - << " static PyMethodDef class_methods[] = {\n"; - - for (fi = object->_methods.begin(); fi != object->_methods.end(); ++fi) { - Function *func = (*fi); - if (!func->_has_this) { - out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name - << ", METH_VARARGS },\n"; - class_methods_size++; - } - } - - out << " };\n" - << " static const int class_methods_size = " << class_methods_size << ";\n\n" - << " if (wrapper == nullptr) {\n" - << " int i;\n" - << " PyObject *bases = PyTuple_New(0);\n" - << " PyObject *dict = PyDict_New();\n" - << "#if PY_MAJOR_VERSION >= 3\n" - << " PyObject *name = PyUnicode_FromString(\"" << python_name << "\");\n" - << "#else\n" - << " PyObject *name = PyString_FromString(\"" << python_name << "\");\n" - << "#endif\n" - << " wrapper = PyClass_New(bases, dict, name);\n" - << " for (i = 0; i < methods_size; ++i) {\n" - << " PyObject *function, *method;\n" - << " function = PyCFunction_New(&methods[i], nullptr);\n" - << " method = PyMethod_New(function, nullptr, wrapper);\n" - << " PyDict_SetItemString(dict, methods[i].ml_name, method);\n" - << " }\n" - << " for (i = 0; i < class_methods_size; ++i) {\n" - << " PyObject *function;\n" - << " function = PyCFunction_New(&class_methods[i], nullptr);\n" - << " PyDict_SetItemString(dict, class_methods[i].ml_name, function);\n" - << " }\n" - << " }\n" - << " return wrapper;\n" - << "}\n\n"; -} - -/** - * Writes the prototype for the indicated function. - */ -void InterfaceMakerPythonObj:: -write_prototype_for(ostream &out, InterfaceMaker::Function *func) { - out << "static PyObject *" - << func->_name << "(PyObject *self, PyObject *args);\n"; -} - -/** - * Writes the definition for a function that will call the indicated C++ - * function or method. - */ -void InterfaceMakerPythonObj:: -write_function_for(ostream &out, InterfaceMaker::Function *func) { - Function::Remaps::const_iterator ri; - out << "/*\n" - << " * Python object wrapper for\n"; - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - out << " * "; - remap->write_orig_prototype(out, 0); - out << "\n"; - } - out << " */\n"; - - out << "static PyObject *" - << func->_name << "(PyObject *, PyObject *args) {\n"; - - // Now write out each instance of the overloaded function. - string expected_params = "Arguments must match one of:"; - - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - expected_params += "\\n "; - write_function_instance(out, 2, func, remap, expected_params); - } - - // If we get here in the generated code, none of the parameters were valid. - // Generate an error exception. (We don't rely on the error already - // generated by ParseTuple(), because it only reports the error for one - // flavor of the function, whereas we might accept multiple flavors for the - // different overloaded C++ function signatures. - - out << " PyErr_SetString(PyExc_TypeError, \"" << expected_params << "\");\n" - << " return nullptr;\n"; - - out << "}\n\n"; -} - -/** - * Writes out the part of a function that handles a single instance of an - * overloaded function. - */ -void InterfaceMakerPythonObj:: -write_function_instance(ostream &out, int indent_level, - InterfaceMaker::Function *func, - FunctionRemap *remap, string &expected_params) { - indent(out, indent_level) << "{\n"; - indent(out, indent_level + 2) << "/* "; - remap->write_orig_prototype(out, 0); - out << " */\n\n"; - - string format_specifiers; - string parameter_list; - vector_string pexprs; - string extra_convert; - string extra_param_check; - string extra_cleanup; - - // Make one pass through the parameter list. We will output a one-line - // temporary variable definition for each parameter, while simultaneously - // building the ParseTuple() function call and also the parameter expression - // list for call_function(). - - expected_params += remap->_cppfunc->get_simple_name(); - expected_params += "("; - - int pn; - for (pn = 0; pn < (int)remap->_parameters.size(); pn++) { - if (pn != 0) { - expected_params += ", "; - } - - indent(out, indent_level + 2); - CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type(); - CPPType *type = remap->_parameters[pn]._remap->get_new_type(); - string param_name = remap->get_parameter_name(pn); - - // This is the string to convert our local variable to the appropriate C++ - // type. Normally this is just a cast. - string pexpr_string = - "(" + type->get_local_name(&parser) + ")" + param_name; - - if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) { - if (TypeManager::is_char_pointer(orig_type)) { - out << "char *" << param_name; - format_specifiers += "s"; - parameter_list += ", &" + param_name; - - } else { - out << "char *" << param_name - << "_str; Py_ssize_t " << param_name << "_len"; - format_specifiers += "s#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - pexpr_string = "basic_string(" + - param_name + "_str, " + - param_name + "_len)"; - } - expected_params += "string"; - - } else if (TypeManager::is_bool(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)"; - expected_params += "bool"; - - } else if (TypeManager::is_unsigned_longlong(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; - extra_param_check += "|| (" + param_name + "_long == nullptr)"; - pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_long);"; - expected_params += "long"; - - } else if (TypeManager::is_longlong(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; - extra_param_check += "|| (" + param_name + "_long == nullptr)"; - pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_long);"; - expected_params += "long"; - - } else if (TypeManager::is_unsigned_integer(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");"; - extra_param_check += "|| (" + param_name + "_uint == nullptr)"; - pexpr_string = "(unsigned int)PyLong_AsUnsignedLong(" + param_name + "_uint)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_uint);"; - expected_params += "unsigned int"; - - } else if (TypeManager::is_integer(type)) { - out << "int " << param_name; - format_specifiers += "i"; - parameter_list += ", &" + param_name; - expected_params += "integer"; - - } else if (TypeManager::is_float(type)) { - out << "double " << param_name; - format_specifiers += "d"; - parameter_list += ", &" + param_name; - expected_params += "float"; - - } else if (TypeManager::is_char_pointer(type)) { - out << "char *" << param_name; - format_specifiers += "s"; - parameter_list += ", &" + param_name; - expected_params += "string"; - - } else if (TypeManager::is_pointer(type)) { - FunctionWriterPtrFromPython *writer = get_ptr_from_python(type); - writer->get_pointer_type()->output_instance(out, param_name, &parser); - format_specifiers += "O&"; - parameter_list += ", &" + writer->get_name() + ", &" + param_name; - expected_params += writer->get_type()->get_preferred_name(); - - } else { - // Ignore a parameter. - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - expected_params += "any"; - } - - if (remap->_parameters[pn]._has_name) { - expected_params += " " + remap->_parameters[pn]._name; - } - - out << ";\n"; - pexprs.push_back(pexpr_string); - } - expected_params += ")"; - - indent(out, indent_level + 2) - << "if (PyArg_ParseTuple(args, \"" << format_specifiers - << "\"" << parameter_list << ")) {\n"; - - if (!extra_convert.empty()) { - indent(out, indent_level + 3) - << extra_convert << "\n"; - } - - if (!extra_param_check.empty()) { - indent(out, indent_level + 4) - << "if (" << extra_param_check.substr(3) << ") {\n"; - if (!extra_cleanup.empty()) { - indent(out, indent_level + 5) - << extra_cleanup << "\n"; - } - indent(out, indent_level + 6) - << "PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n"; - indent(out, indent_level + 6) - << "return nullptr;\n"; - indent(out, indent_level + 4) - << "}\n"; - } - - if (track_interpreter) { - indent(out, indent_level + 4) - << "in_interpreter = 0;\n"; - } - - if (!remap->_void_return && - remap->_return_type->new_type_is_atomic_string()) { - // Treat strings as a special case. We don't want to format the return - // expression. - string return_expr = - remap->call_function(out, indent_level + 4, false, "param0", pexprs); - - CPPType *type = remap->_return_type->get_orig_type(); - indent(out, indent_level + 4); - type->output_instance(out, "return_value", &parser); - out << " = " << return_expr << ";\n"; - - if (track_interpreter) { - indent(out, indent_level + 4) - << "in_interpreter = 1;\n"; - } - if (!extra_cleanup.empty()) { - indent(out, indent_level + 3) - << extra_cleanup << "\n"; - } - - return_expr = manage_return_value(out, indent_level + 4, remap, "return_value"); - test_assert(out, indent_level + 4); - pack_return_value(out, indent_level + 4, remap, return_expr); - - } else { - string return_expr = - remap->call_function(out, indent_level + 4, true, "param0", pexprs); - if (return_expr.empty()) { - if (track_interpreter) { - indent(out, indent_level + 4) - << "in_interpreter = 1;\n"; - } - if (!extra_cleanup.empty()) { - indent(out, indent_level + 3) - << extra_cleanup << "\n"; - } - test_assert(out, indent_level + 4); - indent(out, indent_level + 4) - << "return Py_BuildValue(\"\");\n"; - - } else { - CPPType *type = remap->_return_type->get_temporary_type(); - indent(out, indent_level + 4); - type->output_instance(out, "return_value", &parser); - out << " = " << return_expr << ";\n"; - if (track_interpreter) { - indent(out, indent_level + 4) - << "in_interpreter = 1;\n"; - } - if (!extra_cleanup.empty()) { - indent(out, indent_level + 3) - << extra_cleanup << "\n"; - } - - return_expr = manage_return_value(out, indent_level + 4, remap, "return_value"); - test_assert(out, indent_level + 4); - pack_return_value(out, indent_level + 4, remap, remap->_return_type->temporary_to_return(return_expr)); - } - } - - indent(out, indent_level + 2) << "}\n"; - indent(out, indent_level + 2) - << "PyErr_Clear();\n"; // Clear the error generated by ParseTuple() - indent(out, indent_level) - << "}\n"; -} - -/** - * Outputs a command to pack the indicated expression, of the return_type - * type, as a Python return value. - */ -void InterfaceMakerPythonObj:: -pack_return_value(ostream &out, int indent_level, - FunctionRemap *remap, string return_expr) { - CPPType *orig_type = remap->_return_type->get_orig_type(); - CPPType *type = remap->_return_type->get_new_type(); - - if (remap->_return_type->new_type_is_atomic_string()) { - if (TypeManager::is_char_pointer(orig_type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; - - } else { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromStringAndSize(" - << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize(" - << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; - out << "#endif\n"; - } - - } else if (TypeManager::is_bool(type)) { - indent(out, indent_level) - << "return PyBool_FromLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_unsigned_longlong(type)) { - indent(out, indent_level) - << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_longlong(type)) { - indent(out, indent_level) - << "return PyLong_FromLongLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_unsigned_integer(type)) { - indent(out, indent_level) - << "return PyLong_FromUnsignedLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_integer(type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyLong_FromLong(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyInt_FromLong(" << return_expr << ");\n"; - out << "#endif\n"; - - } else if (TypeManager::is_float(type)) { - indent(out, indent_level) - << "return PyFloat_FromDouble(" << return_expr << ");\n"; - - } else if (TypeManager::is_char_pointer(type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; - - } else if (TypeManager::is_pointer(type)) { - bool caller_manages = remap->_return_value_needs_management; - - FunctionWriterPtrToPython *writer = get_ptr_to_python(type); - indent(out, indent_level) - << "return " << writer->get_name() << "((" - << writer->get_pointer_type()->get_local_name(&parser) << ")" - << return_expr << ", " << caller_manages << ");\n"; - - } else { - // Return None. - indent(out, indent_level) - << "return Py_BuildValue(\"\");\n"; - } -} - -/** - * Returns a FunctionWriter pointer suitable for converting from a Python - * wrapper of the indicated type to the corresponding C++ pointer. - */ -FunctionWriterPtrFromPython *InterfaceMakerPythonObj:: -get_ptr_from_python(CPPType *type) { - PtrConverter::iterator ci; - ci = _from_python.find(type); - if (ci != _from_python.end()) { - // We've previously used this type. - return (FunctionWriterPtrFromPython *)(*ci).second; - } - - FunctionWriter *writer = - _function_writers.add_writer(new FunctionWriterPtrFromPython(type)); - _from_python.insert(PtrConverter::value_type(type, writer)); - return (FunctionWriterPtrFromPython *)writer; -} - -/** - * Returns a FunctionWriter pointer suitable for converting from a C++ pointer - * of the indicated type to the corresponding Python wrapper. - */ -FunctionWriterPtrToPython *InterfaceMakerPythonObj:: -get_ptr_to_python(CPPType *type) { - PtrConverter::iterator ci; - ci = _to_python.find(type); - if (ci != _to_python.end()) { - // We've previously used this type. - return (FunctionWriterPtrToPython *)(*ci).second; - } - - FunctionWriter *writer = - _function_writers.add_writer(new FunctionWriterPtrToPython(type)); - _to_python.insert(PtrConverter::value_type(type, writer)); - return (FunctionWriterPtrToPython *)writer; -} diff --git a/dtool/src/interrogate/interfaceMakerPythonObj.h b/dtool/src/interrogate/interfaceMakerPythonObj.h deleted file mode 100644 index be7e0d9913..0000000000 --- a/dtool/src/interrogate/interfaceMakerPythonObj.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPythonObj.h - * @author drose - * @date 2001-09-19 - */ - -#ifndef INTERFACEMAKERPYTHONOBJ_H -#define INTERFACEMAKERPYTHONOBJ_H - -#include "dtoolbase.h" - -#include "interfaceMakerPython.h" -#include "interrogate_interface.h" - -#include - -class InterrogateType; -class InterrogateFunction; -class FunctionRemap; -class CPPInstance; -class FunctionWriterPtrFromPython; -class FunctionWriterPtrToPython; - -/** - * An InterfaceMaker suitable for generating object-oriented Python code, that - * can be imported and used directly by Python. - */ -class InterfaceMakerPythonObj : public InterfaceMakerPython { -public: - InterfaceMakerPythonObj(InterrogateModuleDef *def); - virtual ~InterfaceMakerPythonObj(); - - virtual void write_prototypes(std::ostream &out,std::ostream *out_h); - virtual void write_functions(std::ostream &out); - - virtual void write_module(std::ostream &out,std::ostream *out_h, InterrogateModuleDef *def); - - virtual bool synthesize_this_parameter(); - - static std::string get_builder_name(CPPType *struct_type); - -protected: - virtual std::string get_wrapper_prefix(); - -private: - void write_class_wrapper(std::ostream &out, Object *object); - void write_prototype_for(std::ostream &out, Function *func); - void write_function_for(std::ostream &out, Function *func); - void write_function_instance(std::ostream &out, int indent_level, Function *func, - FunctionRemap *remap, std::string &expected_params); - - void pack_return_value(std::ostream &out, int indent_level, - FunctionRemap *remap, std::string return_expr); - - FunctionWriterPtrFromPython *get_ptr_from_python(CPPType *type); - FunctionWriterPtrToPython *get_ptr_to_python(CPPType *type); - - typedef std::map PtrConverter; - PtrConverter _from_python; - PtrConverter _to_python; -}; - -#endif diff --git a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx b/dtool/src/interrogate/interfaceMakerPythonSimple.cxx deleted file mode 100644 index 637e6eefad..0000000000 --- a/dtool/src/interrogate/interfaceMakerPythonSimple.cxx +++ /dev/null @@ -1,535 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPythonSimple.cxx - * @author drose - * @date 2001-10-01 - */ - -#include "interfaceMakerPythonSimple.h" -#include "interrogateBuilder.h" -#include "interrogate.h" -#include "functionRemap.h" -#include "parameterRemapUnchanged.h" -#include "typeManager.h" - -#include "interrogateDatabase.h" -#include "interrogateType.h" -#include "interrogateFunction.h" -#include "cppFunctionType.h" - -using std::ostream; -using std::string; - -/** - * - */ -InterfaceMakerPythonSimple:: -InterfaceMakerPythonSimple(InterrogateModuleDef *def) : - InterfaceMakerPython(def) -{ -} - -/** - * - */ -InterfaceMakerPythonSimple:: -~InterfaceMakerPythonSimple() { -} - -/** - * Generates the list of #include ... whatever that's required by this - * particular interface to the indicated output stream. - */ -void InterfaceMakerPythonSimple:: -write_includes(std::ostream &out) { - out << "#if PY_VERSION_HEX >= 0x30300000\n"; - out << "#define Py_LIMITED_API 0x30300000\n"; - out << "#endif\n\n"; - InterfaceMakerPython::write_includes(out); -} - -/** - * Generates the list of function prototypes corresponding to the functions - * that will be output in write_functions(). - */ -void InterfaceMakerPythonSimple:: -write_prototypes(ostream &out,ostream *out_h) { - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - write_prototype_for(out, func); - } - - out << "\n"; - InterfaceMakerPython::write_prototypes(out,out_h); -} - -/** - * Generates the list of functions that are appropriate for this interface. - * This function is called *before* write_prototypes(), above. - */ -void InterfaceMakerPythonSimple:: -write_functions(ostream &out) { - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - write_function_for(out, func); - } - - InterfaceMakerPython::write_functions(out); -} - -/** - * Generates whatever additional code is required to support a module file. - */ -void InterfaceMakerPythonSimple:: -write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) { - InterfaceMakerPython::write_module(out,out_h, def); - - out << "static PyMethodDef python_simple_funcs[] = {\n"; - - FunctionsByIndex::iterator fi; - for (fi = _functions.begin(); fi != _functions.end(); ++fi) { - Function *func = (*fi).second; - Function::Remaps::const_iterator ri; - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - out << " { \"" << remap->_reported_name << "\", &" - << remap->_wrapper_name << ", METH_VARARGS, nullptr },\n"; - } - } - out << " { nullptr, nullptr, 0, nullptr }\n" - << "};\n\n" - - << "#if PY_MAJOR_VERSION >= 3\n" - << "static struct PyModuleDef python_simple_module = {\n" - << " PyModuleDef_HEAD_INIT,\n" - << " \"" << def->module_name << "\",\n" - << " nullptr,\n" - << " -1,\n" - << " python_simple_funcs,\n" - << " nullptr, nullptr, nullptr, nullptr\n" - << "};\n\n" - - << "#define INIT_FUNC PyObject *PyInit_" << def->library_name << "\n" - << "#else\n" - << "#define INIT_FUNC void init" << def->library_name << "\n" - << "#endif\n\n" - - << "#ifdef _WIN32\n" - << "extern \"C\" __declspec(dllexport) INIT_FUNC();\n" - << "#elif __GNUC__ >= 4\n" - << "extern \"C\" __attribute__((visibility(\"default\"))) INIT_FUNC();\n" - << "#else\n" - << "extern \"C\" INIT_FUNC();\n" - << "#endif\n\n" - - << "INIT_FUNC() {\n" - << "#if PY_MAJOR_VERSION >= 3\n" - << " return PyModule_Create(&python_simple_module);\n" - << "#else\n" - << " Py_InitModule(\"" << def->library_name << "\", python_simple_funcs);\n" - << "#endif\n" - << "}\n\n"; -} - -/** - * This method should be overridden and redefined to return true for - * interfaces that require the implicit "this" parameter, if present, to be - * passed as the first parameter to any wrapper functions. - */ -bool InterfaceMakerPythonSimple:: -synthesize_this_parameter() { - return true; -} - -/** - * Returns the prefix string used to generate wrapper function names. - */ -string InterfaceMakerPythonSimple:: -get_wrapper_prefix() { - return "_inP"; -} - -/** - * Returns the prefix string used to generate unique symbolic names, which are - * not necessarily C-callable function names. - */ -string InterfaceMakerPythonSimple:: -get_unique_prefix() { - return "p"; -} - -/** - * Associates the function wrapper with its function in the appropriate - * structures in the database. - */ -void InterfaceMakerPythonSimple:: -record_function_wrapper(InterrogateFunction &ifunc, - FunctionWrapperIndex wrapper_index) { - ifunc._python_wrappers.push_back(wrapper_index); -} - -/** - * Writes the prototype for the indicated function. - */ -void InterfaceMakerPythonSimple:: -write_prototype_for(ostream &out, InterfaceMaker::Function *func) { - Function::Remaps::const_iterator ri; - - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - if (!output_function_names) { - // If we're not saving the function names, don't export it from the - // library. - out << "static "; - } else { - out << "extern \"C\" "; - } - out << "PyObject *" - << remap->_wrapper_name << "(PyObject *self, PyObject *args);\n"; - } -} - -/** - * Writes the definition for a function that will call the indicated C++ - * function or method. - */ -void InterfaceMakerPythonSimple:: -write_function_for(ostream &out, InterfaceMaker::Function *func) { - Function::Remaps::const_iterator ri; - - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - write_function_instance(out, func, remap); - } -} - -/** - * Writes out the particular function that handles a single instance of an - * overloaded function. - */ -void InterfaceMakerPythonSimple::write_function_instance(ostream &out, InterfaceMaker::Function *func, - FunctionRemap *remap) { - out << "/*\n" - << " * Python simple wrapper for\n" - << " * "; - remap->write_orig_prototype(out, 0); - out << "\n" - << " */\n"; - - if (!output_function_names) { - // If we're not saving the function names, don't export it from the - // library. - out << "static "; - } - - out << "PyObject *\n" - << remap->_wrapper_name << "(PyObject *, PyObject *args) {\n"; - - if (generate_spam) { - write_spam_message(out, remap); - } - - string format_specifiers; - string parameter_list; - string container; - vector_string pexprs; - string extra_convert; - string extra_param_check; - string extra_cleanup; - - // Make one pass through the parameter list. We will output a one-line - // temporary variable definition for each parameter, while simultaneously - // building the ParseTuple() function call and also the parameter expression - // list for call_function(). - - int pn; - for (pn = 0; pn < (int)remap->_parameters.size(); ++pn) { - indent(out, 2); - CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type(); - CPPType *type = remap->_parameters[pn]._remap->get_new_type(); - string param_name = remap->get_parameter_name(pn); - - // This is the string to convert our local variable to the appropriate C++ - // type. Normally this is just a cast. - string pexpr_string = - "(" + type->get_local_name(&parser) + ")" + param_name; - - if (remap->_parameters[pn]._remap->new_type_is_atomic_string()) { - if (TypeManager::is_char_pointer(orig_type)) { - out << "char *" << param_name; - format_specifiers += "s"; - parameter_list += ", &" + param_name; - - } else if (TypeManager::is_wstring(orig_type)) { - out << "Py_UNICODE *" << param_name - << "_str; Py_ssize_t " << param_name << "_len"; - format_specifiers += "u#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - pexpr_string = "basic_string((wchar_t *)" + - param_name + "_str, " + - param_name + "_len)"; - - } else { - out << "char *" << param_name - << "_str; Py_ssize_t " << param_name << "_len"; - format_specifiers += "s#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - pexpr_string = "basic_string(" + - param_name + "_str, " + - param_name + "_len)"; - } - - } else if (TypeManager::is_bool(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - pexpr_string = "(PyObject_IsTrue(" + param_name + ")!=0)"; - - } else if (TypeManager::is_unsigned_longlong(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; - extra_param_check += "|| (" + param_name + "_long == nullptr)"; - pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_long);"; - - } else if (TypeManager::is_longlong(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; - extra_param_check += "|| (" + param_name + "_long == nullptr)"; - pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_long);"; - - } else if (TypeManager::is_unsigned_integer(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += " PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");"; - extra_param_check += "|| (" + param_name + "_uint == nullptr)"; - pexpr_string = "(unsigned int)PyLong_AsUnsignedLong(" + param_name + "_uint)"; - extra_cleanup += " Py_XDECREF(" + param_name + "_uint);"; - - } else if (TypeManager::is_integer(type)) { - out << "int " << param_name; - format_specifiers += "i"; - parameter_list += ", &" + param_name; - - } else if (TypeManager::is_float(type)) { - out << "double " << param_name; - format_specifiers += "d"; - parameter_list += ", &" + param_name; - - } else if (TypeManager::is_char_pointer(type)) { - out << "char *" << param_name; - format_specifiers += "s"; - parameter_list += ", &" + param_name; - - } else if (TypeManager::is_pointer_to_PyObject(type)) { - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - pexpr_string = param_name; - - } else if (TypeManager::is_pointer(type)) { - out << "Py_ssize_t " << param_name; - format_specifiers += "n"; - parameter_list += ", &" + param_name; - - } else { - // Ignore a parameter. - out << "PyObject *" << param_name; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - } - - out << ";\n"; - if (remap->_has_this && pn == 0) { - // The "this" parameter gets passed in separately. - container = pexpr_string; - } - pexprs.push_back(pexpr_string); - } - - out << " if (PyArg_ParseTuple(args, \"" << format_specifiers - << "\"" << parameter_list << ")) {\n"; - - if (!extra_convert.empty()) { - out << " " << extra_convert << "\n"; - } - - if (!extra_param_check.empty()) { - out << " if (" << extra_param_check.substr(3) << ") {\n"; - if (!extra_cleanup.empty()) { - out << " " << extra_cleanup << "\n"; - } - out << " PyErr_SetString(PyExc_TypeError, \"Invalid parameters.\");\n" - << " return nullptr;\n" - << " }\n"; - } - - if (track_interpreter) { - out << " in_interpreter = 0;\n"; - } - - if (!remap->_void_return && - remap->_return_type->new_type_is_atomic_string()) { - // Treat strings as a special case. We don't want to format the return - // expression. - string return_expr = remap->call_function(out, 4, false, container, pexprs); - CPPType *type = remap->_return_type->get_orig_type(); - out << " "; - type->output_instance(out, "return_value", &parser); - out << " = " << return_expr << ";\n"; - - if (track_interpreter) { - out << " in_interpreter = 1;\n"; - } - if (!extra_cleanup.empty()) { - out << " " << extra_cleanup << "\n"; - } - - return_expr = manage_return_value(out, 4, remap, "return_value"); - test_assert(out, 4); - pack_return_value(out, 4, remap, return_expr); - - } else { - string return_expr = remap->call_function(out, 4, true, container, pexprs); - if (return_expr.empty()) { - if (track_interpreter) { - out << " in_interpreter = 1;\n"; - } - if (!extra_cleanup.empty()) { - out << " " << extra_cleanup << "\n"; - } - test_assert(out, 4); - out << " return Py_BuildValue(\"\");\n"; - - } else { - CPPType *type = remap->_return_type->get_temporary_type(); - out << " "; - type->output_instance(out, "return_value", &parser); - out << " = " << return_expr << ";\n"; - if (track_interpreter) { - out << " in_interpreter = 1;\n"; - } - if (!extra_cleanup.empty()) { - out << " " << extra_cleanup << "\n"; - } - - return_expr = manage_return_value(out, 4, remap, "return_value"); - test_assert(out, 4); - pack_return_value(out, 4, remap, remap->_return_type->temporary_to_return(return_expr)); - } - } - - out << " }\n"; - - out << " return nullptr;\n"; - out << "}\n\n"; -} - -/** - * Outputs a command to pack the indicated expression, of the return_type - * type, as a Python return value. - */ -void InterfaceMakerPythonSimple:: -pack_return_value(ostream &out, int indent_level, - FunctionRemap *remap, string return_expr) { - CPPType *orig_type = remap->_return_type->get_orig_type(); - CPPType *type = remap->_return_type->get_new_type(); - - if (remap->_return_type->new_type_is_atomic_string()) - { - if (TypeManager::is_char_pointer(orig_type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; - - } else if (TypeManager::is_wstring(orig_type)) { - indent(out, indent_level) - << "return PyUnicode_FromWideChar(" - << return_expr << ".data(), (int)" << return_expr << ".length());\n"; - - } else { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromStringAndSize(" - << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromStringAndSize(" - << return_expr << ".data(), (Py_ssize_t)" << return_expr << ".length());\n"; - out << "#endif\n"; - } - - } else if (TypeManager::is_bool(type)) { - indent(out, indent_level) - << "return PyBool_FromLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_unsigned_longlong(type)) - { - indent(out, indent_level) - << "return PyLong_FromUnsignedLongLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_longlong(type)) - { - indent(out, indent_level) - << "return PyLong_FromLongLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_unsigned_integer(type)) { - indent(out, indent_level) - << "return PyLong_FromUnsignedLong(" << return_expr << ");\n"; - - } else if (TypeManager::is_integer(type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyLong_FromLong(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyInt_FromLong(" << return_expr << ");\n"; - out << "#endif\n"; - - } else if (TypeManager::is_float(type)) { - indent(out, indent_level) - << "return PyFloat_FromDouble(" << return_expr << ");\n"; - - } else if (TypeManager::is_char_pointer(type)) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - indent(out, indent_level) - << "return PyUnicode_FromString(" << return_expr << ");\n"; - out << "#else\n"; - indent(out, indent_level) - << "return PyString_FromString(" << return_expr << ");\n"; - out << "#endif\n"; - - } else if (TypeManager::is_pointer_to_PyObject(type)) { - indent(out, indent_level) - << "return " << return_expr << ";\n"; - - } else if (TypeManager::is_pointer(type)) { - indent(out, indent_level) - << "return PyLong_FromVoidPtr((void*)" << return_expr << ");\n"; - - } else { - // Return None. - indent(out, indent_level) - << "return Py_BuildValue(\"\");\n"; - } -} diff --git a/dtool/src/interrogate/interfaceMakerPythonSimple.h b/dtool/src/interrogate/interfaceMakerPythonSimple.h deleted file mode 100644 index 6e6621ea6d..0000000000 --- a/dtool/src/interrogate/interfaceMakerPythonSimple.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interfaceMakerPythonSimple.h - * @author drose - * @date 2001-10-01 - */ - -#ifndef INTERFACEMAKERPYTHONSIMPLE_H -#define INTERFACEMAKERPYTHONSIMPLE_H - -#include "dtoolbase.h" - -#include "interfaceMakerPython.h" -#include "interrogate_interface.h" - -class FunctionRemap; - -/** - * An InterfaceMaker for generating simple Python function wrappers around C++ - * code. This allows the C++ code to be called by Python, but not necessarily - * in a user-friendly or object-oriented way. - * - * You probably want to use InterfaceMakerPythonObj for a full object-oriented - * solution. This InterfaceMaker is primarily useful as a stopgap for our old - * Python-based FFI system. - */ -class InterfaceMakerPythonSimple : public InterfaceMakerPython { -public: - InterfaceMakerPythonSimple(InterrogateModuleDef *def); - virtual ~InterfaceMakerPythonSimple(); - - virtual void write_includes(std::ostream &out); - virtual void write_prototypes(std::ostream &out,std::ostream *out_h); - virtual void write_functions(std::ostream &out); - - virtual void write_module(std::ostream &out,std::ostream *out_h, InterrogateModuleDef *def); - - virtual bool synthesize_this_parameter(); - -protected: - virtual std::string get_wrapper_prefix(); - virtual std::string get_unique_prefix(); - - virtual void - record_function_wrapper(InterrogateFunction &ifunc, - FunctionWrapperIndex wrapper_index); - -private: - void write_prototype_for(std::ostream &out, Function *func); - void write_function_for(std::ostream &out, Function *func); - void write_function_instance(std::ostream &out, Function *func, - FunctionRemap *remap); - - void pack_return_value(std::ostream &out, int indent_level, - FunctionRemap *remap, std::string return_expr); -}; - -#endif diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx deleted file mode 100644 index d0c2bc96d4..0000000000 --- a/dtool/src/interrogate/interrogate.cxx +++ /dev/null @@ -1,638 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate.cxx - * @author drose - * @date 2000-07-31 - */ - -#include "interrogate.h" -#include "interrogateBuilder.h" - -#include "interrogateDatabase.h" -#include "cppGlobals.h" -#include "pnotify.h" -#include "panda_getopt_long.h" -#include "preprocess_argv.h" -#include - -using std::cerr; -using std::string; - -CPPParser parser; - -Filename output_code_filename; -Filename output_include_filename; -Filename output_data_filename; -Filename source_file_directory; -string output_data_basename; -bool output_module_specific = false; -bool output_function_pointers = false; -bool output_function_names = false; -bool convert_strings = false; -bool manage_reference_counts = false; -bool watch_asserts = false; -bool true_wrapper_names = false; -bool build_c_wrappers = false; -bool build_python_wrappers = false; -bool build_python_obj_wrappers = false; -bool build_python_native = false; -bool track_interpreter = false; -bool save_unique_names = false; -bool no_database = false; -bool generate_spam = false; -bool left_inheritance_requires_upcast = true; -bool mangle_names = true; -CPPVisibility min_vis = V_published; -string library_name; -string module_name; - -// Short command-line options. -static const char *short_options = "I:S:D:F:vh"; - -// Long command-line options. -enum CommandOptions { - CO_oc = 256, - CO_od, - CO_srcdir, - CO_module, - CO_library, - CO_do_module, - CO_fptrs, - CO_fnames, - CO_string, - CO_refcount, - CO_assert, - CO_true_names, - CO_c, - CO_python, - CO_python_obj, - CO_python_native, - CO_track_interpreter, - CO_unique_names, - CO_nodb, - CO_longlong, - CO_promiscuous, - CO_spam, - CO_noangles, - CO_nomangle, - CO_help, -}; - -static struct option long_options[] = { - { "oc", required_argument, nullptr, CO_oc }, - { "od", required_argument, nullptr, CO_od }, - { "srcdir", required_argument, nullptr, CO_srcdir }, - { "module", required_argument, nullptr, CO_module }, - { "library", required_argument, nullptr, CO_library }, - { "do-module", no_argument, nullptr, CO_do_module }, - { "fptrs", no_argument, nullptr, CO_fptrs }, - { "fnames", no_argument, nullptr, CO_fnames }, - { "string", no_argument, nullptr, CO_string }, - { "refcount", no_argument, nullptr, CO_refcount }, - { "assert", no_argument, nullptr, CO_assert }, - { "true-names", no_argument, nullptr, CO_true_names }, - { "c", no_argument, nullptr, CO_c }, - { "python", no_argument, nullptr, CO_python }, - { "python-obj", no_argument, nullptr, CO_python_obj }, - { "python-native", no_argument, nullptr, CO_python_native }, - { "track-interpreter", no_argument, nullptr, CO_track_interpreter }, - { "unique-names", no_argument, nullptr, CO_unique_names }, - { "nodb", no_argument, nullptr, CO_nodb }, - { "longlong", required_argument, nullptr, CO_longlong }, - { "promiscuous", no_argument, nullptr, CO_promiscuous }, - { "spam", no_argument, nullptr, CO_spam }, - { "noangles", no_argument, nullptr, CO_noangles }, - { "nomangle", no_argument, nullptr, CO_nomangle }, - { "help", no_argument, nullptr, CO_help }, - { nullptr } -}; - -void -show_usage() { - cerr - << "\nUsage:\n" - << " interrogate [opts] file.C [file.C ...]\n" - << " interrogate -h\n\n"; -} - -void show_help() { - show_usage(); - cerr - << "Interrogate is a program to parse a body of C++ code and build up a table\n" - << "of classes, methods, functions, and symbols found, for the purposes of\n" - << "calling into the codebase via a non-C++ scripting language like Scheme,\n" - << "Smalltalk, or Python.\n\n" - - << "In addition to identifying all the classes and their relationships,\n" - << "interrogate will generate a wrapper function for each callable function.\n" - << "The wrapper functions will be callable directly from the scripting language,\n" - << "with no understanding of C++ necessary; these wrapper functions will in turn\n" - << "call the actual C++ functions or methods.\n\n" - - << "Most exportable features of C++ are supported, including templates, default\n" - << "parameters, and function overloading.\n\n" - - << "Options:\n\n" - - << " -oc output.C\n" - << " Specify the name of the file to which generated code will be written.\n" - << " This includes all of the function wrappers, as well as those tables\n" - << " which must be compiled into the library.\n\n" - - << " -od output.in\n" - << " Specify the name of the file to which the non-compiled data tables\n" - << " will be written. This file describes the relationships between\n" - << " all the types and the functions, and associates the function wrappers\n" - << " above with this data. This file will be opened and read at runtime\n" - << " when the scripting language first calls some interrogate query\n" - << " function.\n\n" - - << " -srcdir directory\n" - << " Specify the name of the directory to which the source filenames are\n" - << " relative.\n\n" - - << " -module module_name\n" - << " Defines the name of the module this data is associated with. This\n" - << " is strictly a code-organizational tool. Conceptually, a module is\n" - << " the highest level of grouping for interrogate data; a module may\n" - << " contain several libraries. If this is omitted, no module name is\n" - << " specified.\n\n" - - << " Sometimes, depending on the type of wrappers being generated, there\n" - << " may be additional code that needs to be generated on the module\n" - << " level, above that which was already generated at the library level.\n" - << " Python, for instance, generates the table of python-callable function\n" - << " wrappers at the module level. Use the program interrogate-module\n" - << " to generate the appropriate code at the module level.\n\n" - - << " -library library_name\n" - << " Defines the name of the library this data is associated with. This\n" - << " is another code-organizational tool. Typically, there will be one\n" - << " invocation of interrogate for each library, and there will be\n" - << " multiple libraries per module. If this is omitted, no library name\n" - << " is specified.\n\n" - - << " -do-module\n" - << " Generate whatever module-level code should be generated immediately,\n" - << " rather than waiting for a special interrogate-module pass.\n" - << " This, of course, prohibits grouping several libraries together\n" - << " into a single module.\n\n" - - << " -fptrs\n" - << " Make void* pointers to the function wrappers directly available. A\n" - << " scripting language will be able to call the interrogate functions\n" - << " directly by pointer.\n\n" - - << " -fnames\n" - << " Make the names of the function wrappers public symbols so that the\n" - << " scripting language will be able to call the interrogate functions\n" - << " by name.\n\n" - - << " Either or both of -fptrs and/or -fnames may be specified. If both are\n" - << " omitted, the default is -fnames.\n\n" - - << " -string\n" - << " Treat char* and basic_string as special cases, and map\n" - << " parameters of these types to type atomic string. The scripting\n" - << " language will see only functions that receive and return strings,\n" - << " not pointers to character or structures of basic_string.\n" - << " If C calling convention wrappers are being generated, the atomic\n" - << " string type means type char*. In any other calling convention, the\n" - << " atomic string type is whatever the native string type is.\n\n" - - << " -refcount\n" - << " Treat classes that inherit from a class called ReferenceCount as a\n" - << " special case. Any wrapper function that returns a pointer to\n" - << " one of these classes will automatically increment the reference\n" - << " count by calling ref() on the object first, and any destructors\n" - << " that are generated will call unref_delete() on the object instead of\n" - << " simply delete.\n\n" - << " Furthermore, parameters of type PointerTo or ConstPointerTo\n" - << " will automatically be mapped to N * and const N *, respectively.\n\n" - - << " -assert\n" - << " Generate code in each wrapper that will check the state of the assert\n" - << " flag and trigger an exception in the scripting language when a\n" - << " C++ assertion fails. Presently, this only has meaning to the Python\n" - << " wrappers.\n\n" - - << " -true-names\n" - << " Use the actual name of the function being wrapped as the name of\n" - << " the generated wrapper function, instead of an ugly hash name.\n" - << " This means the wrapper functions may be called directly using a\n" - << " meaningful name (especially if -fnames is also given), but it\n" - << " also means that C++ function overloading (including default values\n" - << " for parameters) cannot be used, as it will lead to multiple wrapper\n" - << " functions with the same name.\n\n" - - << " -c\n" - << " Generate function wrappers using the C calling convention. Any\n" - << " scripting language that can call a C function should be able to\n" - << " make advantage of the interrogate database.\n\n" - << " -python\n" - << " Generate function wrappers using the Python calling convention.\n" - << " The shared library will be directly loadable as a Python module\n" - << " (especially if the module definitions are made available either by\n" - << " running interrogate-module later, or by specifying -do-module on\n" - << " the command line now). However, C++ objects and methods will be\n" - << " converted into an object handle and a list of independent Python\n" - << " functions.\n\n" - << " -python-obj\n" - << " Generate Python function wrappers that convert C++ objects to true\n" - << " python objects, with all methods converted to Python methods. This\n" - << " is currently experimental.\n\n" - << " -python-native\n" - << " Generate Python function wrappers that convert C++ objects to true\n" - << " python objects, with all methods converted to Python methods. This\n" - << " is currently experimental.\n\n" - - << " Any combination of -c, -python, or -python-obj may be specified. If all\n" - << " are omitted, the default is -c.\n\n" - - << " -track-interpreter\n" - << " Generate code within each wrapper function to adjust the global\n" - << " variable \"in_interpreter\" to indicated whether code is running\n" - << " within the Panda C++ environment or within the high-level language.\n" - - << " -unique-names\n" - << " Compile a table into the library (i.e. generate code into the -oc\n" - << " file) that defines a lookup of each function wrapper by its unique\n" - << " name. This makes it possible to consistently identify function\n" - << " wrappers between sessions, at the cost of having this additional\n" - << " table in memory.\n\n" - - << " -nodb\n" - << " Do not build a full interrogate database, but just generate function\n" - << " wrappers. It is assumed that the user will know how to call the\n" - << " function wrappers already, from some external source. This is most\n" - << " useful in conjunction with -true-names.\n\n" - - << " -promiscuous\n" - << " Export *all* public symbols, functions, and classes seen, even those\n" - << " not explicitly marked to be published.\n\n" - - << " -spam\n" - << " Generate wrapper functions that report each invocation to Notify.\n" - << " This can sometimes be useful for tracking down bugs.\n\n" - - << " -noangles\n" - << " Treat #include the same as #include \"file\". This means -I\n" - << " and -S are equivalent.\n\n" - - << " -nomangle\n" - << " Do not generate camelCase equivalents of functions.\n\n"; -} - -// handle commandline -D options -static void -predefine_macro(CPPParser& parser, const string& inoption) { - string macro_name, macro_def; - - size_t eq = inoption.find('='); - if (eq != string::npos) { - macro_name = inoption.substr(0, eq); - macro_def = inoption.substr(eq + 1); - } else { - macro_name = inoption; - } - - CPPManifest *macro = new CPPManifest(parser, macro_name, macro_def); - parser._manifests[macro->_name] = macro; -} - -int -main(int argc, char **argv) { - preprocess_argv(argc, argv); - string command_line; - int i; - for (i = 0; i < argc; i++) { - if (i > 0) { - command_line += ' '; - } - command_line += string(argv[i]); - } - - Filename fn; - extern char *optarg; - extern int optind; - int flag; - - flag = getopt_long_only(argc, argv, short_options, long_options, nullptr); - while (flag != EOF) { - switch (flag) { - case 'I': - fn = Filename::from_os_specific(optarg); - fn.make_absolute(); - parser._quote_include_path.append_directory(fn); - parser._quote_include_kind.push_back(CPPFile::S_alternate); - break; - - case 'S': - fn = Filename::from_os_specific(optarg); - fn.make_absolute(); - parser._angle_include_path.append_directory(fn); - parser._quote_include_path.append_directory(fn); - parser._quote_include_kind.push_back(CPPFile::S_system); - break; - - case 'D': - predefine_macro(parser, optarg); - break; - - case 'F': - // This is just a compile directive which we ignore. - break; - - case 'v': - parser.set_verbose(parser.get_verbose() + 1); - break; - - case CO_oc: - output_code_filename = Filename::from_os_specific(optarg); - output_code_filename.make_absolute(); - break; - - case CO_od: - output_data_filename = Filename::from_os_specific(optarg); - output_data_filename.make_absolute(); - break; - - case CO_srcdir: - source_file_directory = Filename::from_os_specific(optarg); - source_file_directory.make_absolute(); - break; - - case CO_module: - module_name = optarg; - break; - - case CO_library: - library_name = optarg; - break; - - case CO_do_module: - output_module_specific = true; - break; - - case CO_fptrs: - output_function_pointers = true; - break; - - case CO_fnames: - output_function_names = true; - break; - - case CO_string: - convert_strings = true; - break; - - case CO_refcount: - manage_reference_counts = true; - break; - - case CO_assert: - watch_asserts = true; - break; - - case CO_true_names: - true_wrapper_names = true; - break; - - case CO_c: - build_c_wrappers = true; - break; - - case CO_python: - build_python_wrappers = true; - break; - - case CO_python_obj: - build_python_obj_wrappers = true; - break; - - case CO_python_native: - build_python_native = true; - break; - - case CO_track_interpreter: - track_interpreter = true; - break; - - case CO_unique_names: - save_unique_names = true; - break; - - case CO_nodb: - no_database = true; - break; - - case CO_longlong: - cerr << "Warning: ignoring deprecated -longlong option.\n"; - cpp_longlong_keyword = optarg; - break; - - case CO_promiscuous: - min_vis = V_public; - break; - - case CO_spam: - generate_spam = true; - break; - - case CO_noangles: - parser._noangles = true; - break; - - case CO_nomangle: - mangle_names = false; - break; - - case 'h': - case CO_help: - show_help(); - exit(0); - - default: - exit(1); - } - flag = getopt_long_only(argc, argv, short_options, long_options, nullptr); - } - - argc -= (optind-1); - argv += (optind-1); - - if (argc < 2) { - show_usage(); - exit(1); - } - - // If requested, change directory to the source-file directory. - if (source_file_directory != "") { - if (!source_file_directory.chdir()) { - cerr << "Could not change directory to " << source_file_directory << "\n"; - exit(1); - } - } - -// if(!output_code_filename.empty()) { output_include_filename = -// output_code_filename.get_fullpath_wo_extension() +".h"; printf(" Include -// File Will be Set to %s \n",output_include_filename.c_str()); } - - output_code_filename.set_text(); - output_data_filename.set_text(); -// output_include_filename.set_text(); - output_data_basename = output_data_filename.get_basename(); - - if (output_function_names && true_wrapper_names) { - cerr - << "Cannot simultaneously export function names and report\n" - << "true wrapper names--wrapper names will clash with the\n" - << "wrapped functions!\n"; - exit(1); - } - - if (!build_c_wrappers && !build_python_wrappers && - !build_python_obj_wrappers &&!build_python_native) { - build_c_wrappers = true; - } - - // Add all of the .h files we are explicitly including to the parser. - for (i = 1; i < argc; ++i) { - Filename filename = Filename::from_os_specific(argv[i]); - filename.make_absolute(); - parser._explicit_files.insert(filename); - } - - // Now go through them again and feed them into the C++ parser. - for (i = 1; i < argc; ++i) { - Filename filename = Filename::from_os_specific(argv[i]); - if (!parser.parse_file(filename)) { - cerr << "interrogate failed to parse file: '" << argv[i] << "'\n"; - exit(1); - } - builder.add_source_file(filename.to_os_generic()); - } - - // Now that we've parsed all the source code, change the way things are - // output from now on so we can compile our generated code using VC++. - // Sheesh. - - // Actually, don't do this any more, since it bitches some of the logic - // (particularly with locating alt names), and it shouldn't be necessary - // with modern VC++. cppparser_output_class_keyword = false; - - // Now look for the .N files. - for (i = 1; i < argc; ++i) { - Filename filename = Filename::from_os_specific(argv[i]); - Filename nfilename = filename; - nfilename.set_extension("N"); - nfilename.set_text(); - pifstream nfile; - if (nfilename.open_read(nfile)) { - builder.read_command_file(nfile); - } - } - - builder.build(); - - // Make up a file identifier. This is just some bogus number that should be - // the same in both the compiled-in code and in the database, so we can - // check synchronicity at load time. - // We allow overriding this value by setting SOURCE_DATE_EPOCH to support - // reproducible builds. - int file_identifier; -#ifdef _MSC_VER - char source_date_epoch[64]; - size_t source_date_epoch_size = 0; - if (getenv_s(&source_date_epoch_size, source_date_epoch, - sizeof(source_date_epoch), "SOURCE_DATE_EPOCH"), source_date_epoch_size > 1) { -#else - const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); - if (source_date_epoch != nullptr && source_date_epoch[0] != 0) { -#endif - file_identifier = atoi(source_date_epoch); - } else { - file_identifier = time(nullptr); - } - InterrogateModuleDef *def = builder.make_module_def(file_identifier); - - pofstream * the_output_include = nullptr; - pofstream output_include; - - - if (1==2 && !output_include_filename.empty()) - { - output_include_filename.open_write(output_include); - - output_include << "#ifndef " << output_include_filename.get_basename_wo_extension() << "__HH__\n"; - output_include << "#define " << output_include_filename.get_basename_wo_extension() << "__HH__\n"; - - output_include - << "/*\n" - << " * This file was generated by:\n" - << " * " << command_line << "\n" - << " *\n" - << " */\n\n"; - - - if (output_include.fail()) - { - nout << "Unable to write to " << output_include_filename << "\n"; - exit(-1); - } - the_output_include = &output_include; - } - - int status = 0; - - // Now output all of the wrapper functions. - if (!output_code_filename.empty()) - { - pofstream output_code; - output_code_filename.open_write(output_code); - - output_code - << "/*\n" - << " * This file was generated by:\n" - << " * " << command_line << "\n" - << " *\n" - << " */\n\n"; - - if (the_output_include != nullptr) { - output_code << "#include \"" << output_include_filename << "\"\n"; - *the_output_include << "#include \"" << output_include_filename.get_fullpath_wo_extension() << "_pynative.h\"\n"; - } - - if (output_code.fail()) { - nout << "Unable to write to " << output_code_filename << "\n"; - status = -1; - } else { - builder.write_code(output_code, the_output_include, def); - } - } - - if (the_output_include != nullptr) { - *the_output_include << "#endif // #define " << output_include_filename.get_basename_wo_extension() << "__HH__\n"; - } - - // And now output the bulk of the database. - if (!output_data_filename.empty()) { - pofstream output_data; - output_data_filename.open_write(output_data); - - if (output_data.fail()) { - nout << "Unable to write to " << output_data_filename << "\n"; - status = -1; - } else { - InterrogateDatabase::get_ptr()->write(output_data, def); - } - } - - return status; -} diff --git a/dtool/src/interrogate/interrogate.h b/dtool/src/interrogate/interrogate.h deleted file mode 100644 index a40a1ed26e..0000000000 --- a/dtool/src/interrogate/interrogate.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate.h - * @author drose - * @date 2000-07-31 - */ - -#ifndef INTERROGATE_H -#define INTERROGATE_H - -#include "dtoolbase.h" - -#include "cppParser.h" -#include "cppVisibility.h" -#include "filename.h" - -extern CPPParser parser; - -// A few global variables that control the interrogate process. -extern Filename output_code_filename; -extern Filename output_data_filename; -extern std::string output_data_basename; -extern bool output_module_specific; -extern bool output_function_pointers; -extern bool output_function_names; -extern bool convert_strings; -extern bool manage_reference_counts; -extern bool watch_asserts; -extern bool true_wrapper_names; -extern bool build_c_wrappers; -extern bool build_python_wrappers; -extern bool build_python_obj_wrappers; -extern bool build_python_native; -extern bool track_interpreter; -extern bool save_unique_names; -extern bool no_database; -extern bool generate_spam; -extern bool left_inheritance_requires_upcast; -extern bool mangle_names; -extern CPPVisibility min_vis; -extern std::string library_name; -extern std::string module_name; - -#endif diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx deleted file mode 100644 index 45222f6a9c..0000000000 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ /dev/null @@ -1,3214 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateBuilder.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "interrogateBuilder.h" -#include "interrogate.h" -#include "parameterRemap.h" -#include "typeManager.h" -#include "functionWriters.h" -#include "interfaceMakerC.h" -#include "interfaceMakerPythonObj.h" -#include "interfaceMakerPythonSimple.h" -#include "interfaceMakerPythonNative.h" -#include "functionRemap.h" - -#include "interrogateType.h" -#include "interrogateDatabase.h" -#include "indexRemapper.h" -#include "cppParser.h" -#include "cppDeclaration.h" -#include "cppFunctionGroup.h" -#include "cppFunctionType.h" -#include "cppParameterList.h" -#include "cppInstance.h" -#include "cppSimpleType.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" -#include "cppArrayType.h" -#include "cppConstType.h" -#include "cppExtensionType.h" -#include "cppStructType.h" -#include "cppExpression.h" -#include "cppTypedefType.h" -#include "cppTypeDeclaration.h" -#include "cppEnumType.h" -#include "cppCommentBlock.h" -#include "cppMakeProperty.h" -#include "cppMakeSeq.h" -#include "pnotify.h" - -#include -#include - -using std::cerr; -using std::istream; -using std::map; -using std::ostream; -using std::ostringstream; -using std::string; - -InterrogateBuilder builder; -std::string EXPORT_IMPORT_PREFIX; - -/** - * Adds the given source filename to the list of files that we are scanning. - * Those source files that appear to be header files will be #included in the - * generated code file. - */ -void InterrogateBuilder:: -add_source_file(const string &filename) { - if (filename.empty()) { - return; - } - - _include_files[filename] = '"'; -} - -/** - * Reads a .N file that might contain control information for the interrogate - * process. - */ -void InterrogateBuilder:: -read_command_file(istream &in) { - string line; - std::getline(in, line); - while (!in.fail() && !in.eof()) { - // Strip out the comment. - size_t hash = line.find('#'); - if (hash != string::npos) { - line = line.substr(0, hash); - } - - // Skip leading whitespace. - size_t p = 0; - while (p < line.length() && isspace(line[p])) { - p++; - } - - if (p < line.length()) { - // Get the first word. - size_t q = p; - while (q < line.length() && !isspace(line[q])) { - q++; - } - string command = line.substr(p, q - p); - - // Get the rest. - p = q; - while (p < line.length() && isspace(line[p])) { - p++; - } - // Except for the trailing whitespace. - q = line.length(); - while (q > p && isspace(line[q - 1])) { - q--; - } - string params = line.substr(p, q - p); - - do_command(command, params); - } - std::getline(in, line); - } -} - -/** - * Executes a single command as read from the .N file. - */ -void InterrogateBuilder:: -do_command(const string &command, const string ¶ms) { - - if (command == "forcevisible") { - CPPType *type = parser.parse_type(params); - if (type == nullptr) { - nout << "Unknown type: allowtype " << params << "\n"; - } else { - type = type->resolve_type(&parser, &parser); - type->_vis = min_vis; - } - - } else if (command == "forcetype") { - // forcetype explicitly exports the given type. - CPPType *type = parser.parse_type(params); - if (type == nullptr) { - nout << "Unknown type: forcetype " << params << "\n"; - } else { - type = type->resolve_type(&parser, &parser); - type->_forcetype = true; - _forcetype.insert(type->get_local_name(&parser)); - } - - } else if (command == "renametype") { - // rename exports the type as the indicated name. We strip off the last - // word as the new name; the new name may not contain spaces (although the - // original type name may). - - size_t space = params.rfind(' '); - if (space == string::npos) { - nout << "No new name specified for renametype " << params << "\n"; - } else { - string orig_name = params.substr(0, space); - string new_name = params.substr(space + 1); - - CPPType *type = parser.parse_type(orig_name); - if (type == nullptr) { - nout << "Unknown type: renametype " << orig_name << "\n"; - } else { - type = type->resolve_type(&parser, &parser); - _renametype[type->get_local_name(&parser)] = new_name; - } - } - - } else if (command == "ignoretype") { - // ignoretype explicitly ignores the given type. - CPPType *type = parser.parse_type(params); - if (type == nullptr) { - nout << "Unknown type: ignoretype " << params << "\n"; - } else { - type = type->resolve_type(&parser, &parser); - _ignoretype.insert(type->get_local_name(&parser)); - } - - } else if (command == "defconstruct") { - // defining the parameters that are implicitly supplied to the generated - // default constructor. Especially useful for linmath objects, whose - // default constructor in C++ is uninitialized, but whose Python-level - // constructor should initialize to 0. - - size_t space = params.find(' '); - if (space == string::npos) { - nout << "No constructor specified for defconstruct " << params << "\n"; - } else { - string class_name = params.substr(0, space); - string constructor = params.substr(space + 1); - - CPPType *type = parser.parse_type(class_name); - if (type == nullptr) { - nout << "Unknown type: defconstruct " << class_name << "\n"; - } else { - type = type->resolve_type(&parser, &parser); - _defconstruct[type->get_local_name(&parser)] = constructor; - } - } - - } else if (command == "ignoreinvolved") { - _ignoreinvolved.insert(params); - - } else if (command == "ignorefile") { - insert_param_list(_ignorefile, params); - - } else if (command == "ignoremember") { - insert_param_list(_ignoremember, params); - - } else if (command == "noinclude") { - insert_param_list(_noinclude, params); - - } else if (command == "forceinclude") { - size_t nchars = params.size(); - if (nchars >= 2 && params[0] == '"' && params[nchars-1] == '"') { - string incfile = params.substr(1, nchars - 2); - _include_files[incfile] = '"'; - - } else if (nchars >= 2 && params[0] == '<' && params[nchars-1] == '>') { - string incfile = params.substr(1, nchars - 2); - _include_files[incfile] = '<'; - - } else { - nout << "Ignoring invalid forceinclude " << params << "\n" - "Expected to be in one of the following forms:\n" - " forceinclude \"file.h\"\n" - " forceinclude \n"; - } - } else { - nout << "Ignoring " << command << " " << params << "\n"; - } -} - -/** - * Builds all of the interrogate data. - */ -void InterrogateBuilder:: -build() { - _library_hash_name = hash_string(library_name, 5); - - // Make sure we have the complete set of #includes we need. - CPPParser::Includes::const_iterator ii; - for (ii = parser._quote_includes.begin(); - ii != parser._quote_includes.end(); - ++ii) { - const string &filename = (*ii); - _include_files[filename] = '"'; - } - for (ii = parser._angle_includes.begin(); - ii != parser._angle_includes.end(); - ++ii) { - const string &filename = (*ii); - _include_files[filename] = '<'; - } - - // First, get all the types that were explicitly forced. - Commands::const_iterator ci; - for (ci = _forcetype.begin(); - ci != _forcetype.end(); - ++ci) { - CPPType *type = parser.parse_type(*ci); - if (type == nullptr) { - cerr << "Failure to parse forcetype " << *ci << "\n"; - } - assert(type != nullptr); - get_type(type, true); - } - - // Now go through all of the top-level declarations in the file(s). - - CPPScope::Declarations::const_iterator di; - for (di = parser._declarations.begin(); - di != parser._declarations.end(); - ++di) { - if ((*di)->get_subtype() == CPPDeclaration::ST_instance) { - CPPInstance *inst = (*di)->as_instance(); - if (inst->_type->get_subtype() == CPPDeclaration::ST_function) { - // Here's a function declaration. - scan_function(inst); - } else { - // Here's a data element declaration. - scan_element(inst, nullptr, &parser); - } - - } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) { - CPPTypedefType *tdef = (*di)->as_typedef_type(); - - if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) { - // A typedef counts as a declaration. This lets us pick up most - // template instantiations. - CPPStructType *struct_type = - tdef->_type->resolve_type(&parser, &parser)->as_struct_type(); - scan_struct_type(struct_type); - } - - scan_typedef_type(tdef); - - } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) { - CPPType *type = (*di)->as_type_declaration()->_type; - - type->_vis = (*di)->_vis; - - if (type->get_subtype() == CPPDeclaration::ST_struct) { - CPPStructType *struct_type = - type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); - scan_struct_type(struct_type); - - } else if (type->get_subtype() == CPPDeclaration::ST_enum) { - CPPEnumType *enum_type = - type->as_type()->resolve_type(&parser, &parser)->as_enum_type(); - scan_enum_type(enum_type); - } - } - } - - CPPPreprocessor::Manifests::const_iterator mi; - for (mi = parser._manifests.begin(); mi != parser._manifests.end(); ++mi) { - CPPManifest *manifest = (*mi).second; - scan_manifest(manifest); - } - - // Now that we've gone through all the code and generated all the functions - // and types, build the function wrappers. make_wrappers(); -} - -/** - * Generates all the code necessary to the indicated output stream. - */ -void InterrogateBuilder:: -write_code(ostream &out_code,ostream * out_include, InterrogateModuleDef *def) { - typedef std::vector InterfaceMakers; - InterfaceMakers makers; - - if (build_c_wrappers) { - InterfaceMaker *maker = new InterfaceMakerC(def); - makers.push_back(maker); - } - - if (build_python_wrappers) { - InterfaceMaker *maker = new InterfaceMakerPythonSimple(def); - makers.push_back(maker); - } - - if (build_python_obj_wrappers) { - InterfaceMaker *maker = new InterfaceMakerPythonObj(def); - makers.push_back(maker); - } - - if (build_python_native) { - InterfaceMakerPythonNative *maker = new InterfaceMakerPythonNative(def); - makers.push_back(maker); - } - - EXPORT_IMPORT_PREFIX = std::string("EXPCL_") + def->module_name; - for (size_t i = 0; i < EXPORT_IMPORT_PREFIX.size(); i++) { - EXPORT_IMPORT_PREFIX[i] = toupper(EXPORT_IMPORT_PREFIX[i]); - } - - InterfaceMakers::iterator mi; - // First, make all the wrappers. - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->generate_wrappers(); - } - - // Now generate all the function bodies to a temporary buffer. By - // generating these first, we ensure that we know all of the pointers we'll - // be using ahead of time (and can therefore generate correct prototypes). - ostringstream function_bodies; - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_functions(function_bodies); - } - - // Now, begin the actual output. Start with the #include lines. - if (!no_database) { - out_code << "#include \"dtoolbase.h\"\n" - << "#include \"interrogate_request.h\"\n" - << "#include \"dconfig.h\"\n"; - } - - ostringstream declaration_bodies; - - if (watch_asserts) { - declaration_bodies << "#include \"pnotify.h\"\n"; - } - - declaration_bodies << "#include \n"; - - if (build_python_native) { - declaration_bodies << "#include \"py_panda.h\"\n"; - declaration_bodies << "#include \"extension.h\"\n"; - declaration_bodies << "#include \"dcast.h\"\n"; - } - declaration_bodies << "\n"; - - IncludeFiles::const_iterator ifi; - for (ifi = _include_files.begin(); - ifi != _include_files.end(); - ++ifi) { - const string &filename = (*ifi).first; - char delimiter = (*ifi).second; - if (should_include(filename)) { - if (delimiter == '"') { - declaration_bodies << "#include \"" << filename << "\"\n"; - } else { - declaration_bodies << "#include <" << filename << ">\n"; - } - } - } - declaration_bodies << "\n"; - - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_includes(declaration_bodies); - } - - if (generate_spam) { - declaration_bodies << "#include \"config_interrogatedb.h\"\n" - << "#include \"notifyCategoryProxy.h\"\n\n" - << "NotifyCategoryDeclNoExport(in_" << library_name << ");\n" - << "NotifyCategoryDef(in_" << library_name << ", interrogatedb_cat);\n\n"; - } - - declaration_bodies << "\n"; - - // And now the prototypes. - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_prototypes(declaration_bodies,out_include); - } - declaration_bodies << "\n"; - -// if(out_include != NULL) (*out_include) << declaration_bodies.str(); else - out_code << declaration_bodies.str(); - - // Followed by the function bodies. - out_code << function_bodies.str() << "\n"; - - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_module_support(out_code, out_include, def); - } - - if (output_module_specific) { - // Output whatever stuff we should output if this were a module. - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->write_module(out_code, out_include, def); - } - } - - // Now collect all the function wrappers. - std::vector remaps; - for (mi = makers.begin(); mi != makers.end(); ++mi) { - (*mi)->get_function_remaps(remaps); - } - - // Make sure all of the function wrappers appear first in the set of - // indices, and that they occupy consecutive index numbers, so we can build - // a simple array of function pointers by index. - remap_indices(remaps); - - // Get the function wrappers in index-number order. - int num_wrappers = 0; - map wrappers_by_index; - - std::vector::iterator ri; - for (ri = remaps.begin(); ri != remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - wrappers_by_index[remap->_wrapper_index] = remap; - num_wrappers++; - } - - if (output_function_pointers) { - // Write out the table of function pointers. - out_code << "static void *_in_fptrs[" << num_wrappers << "] = {\n"; - int next_index = 1; - map::iterator ii; - for (ii = wrappers_by_index.begin(); - ii != wrappers_by_index.end(); - ++ii) { - int this_index = (*ii).first; - while (next_index < this_index) { - out_code << " (void *)0,\n"; - next_index++; - } - assert(next_index == this_index); - FunctionRemap *remap = (*ii).second; - - out_code << " (void *)&" << remap->_wrapper_name << ",\n"; - next_index++; - } - while (next_index < num_wrappers + 1) { - out_code << " (void *)0,\n"; - next_index++; - } - out_code << "};\n\n"; - } - - if (save_unique_names) { - // Write out the table of unique names, in no particular order. - out_code << "static InterrogateUniqueNameDef _in_unique_names[" - << num_wrappers << "] = {\n"; - for (ri = remaps.begin(); ri != remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - out_code << " { \"" - << remap->_unique_name << "\", " - << remap->_wrapper_index - 1 << " },\n"; - } - out_code << "};\n\n"; - } - - if (!no_database) { - // Now build the module definition structure to add ourselves to the - // global interrogate database. - out_code << "static InterrogateModuleDef _in_module_def = {\n" - << " " << def->file_identifier << ", /* file_identifier */\n" - << " \"" << def->library_name << "\", /* library_name */\n" - << " \"" << def->library_hash_name << "\", /* library_hash_name */\n" - << " \"" << def->module_name << "\", /* module_name */\n"; - if (def->database_filename != nullptr) { - out_code << " \"" << def->database_filename - << "\", /* database_filename */\n"; - } else { - out_code << " (const char *)0, /* database_filename */\n"; - } - - if (save_unique_names) { - out_code << " _in_unique_names,\n" - << " " << num_wrappers << ", /* num_unique_names */\n"; - } else { - out_code << " nullptr, /* unique_names */\n" - << " 0, /* num_unique_names */\n"; - } - - if (output_function_pointers) { - out_code << " _in_fptrs,\n" - << " " << num_wrappers << ", /* num_fptrs */\n"; - } else { - out_code << " nullptr, /* fptrs */\n" - << " 0, /* num_fptrs */\n"; - } - - out_code << " 1, /* first_index */\n" - << " " << InterrogateDatabase::get_ptr()->get_next_index() - << " /* next_index */\n" - << "};\n\n"; - - // And now write the static-init code that tells the interrogate database - // to load up this module. - out_code << "Configure(_in_configure_" << library_name << ");\n" - << "ConfigureFn(_in_configure_" << library_name << ") {\n" - << " interrogate_request_module(&_in_module_def);\n" - << "}\n\n"; - } -} - -/** - * Allocates and returns a new InterrogateModuleDef structure that reflects - * the data we have just build, or at least that subset of the - * InterrogateModuleDef data that we have available at this time. - * - * The data in this structure may include pointers that reference directly - * into the InterrogateBuilder object; thus, this structure is only valid for - * as long as the builder itself remains in scope. - */ -InterrogateModuleDef *InterrogateBuilder:: -make_module_def(int file_identifier) { - InterrogateModuleDef *def = new InterrogateModuleDef; - memset(def, 0, sizeof(InterrogateModuleDef)); - - def->file_identifier = file_identifier; - def->library_name = library_name.c_str(); - def->library_hash_name = _library_hash_name.c_str(); - def->module_name = module_name.c_str(); - if (!output_data_filename.empty()) { - def->database_filename = output_data_basename.c_str(); - } - - return def; -} - -/** - * Adjusts the given string to remove any characters we don't want to export - * as part of an identifier name. Returns the cleaned string. - * - * This replaces any consecutive invalid characters with an underscore. - */ -string InterrogateBuilder:: -clean_identifier(const string &name) { - string result; - - bool last_invalid = false; - - string::const_iterator ni; - for (ni = name.begin(); ni != name.end(); ++ni) { - if (isalnum(*ni)) { - if (last_invalid) { - result += '_'; - last_invalid = false; - } - result += (*ni); - } else { - last_invalid = true; - } - } - - return result; -} - -/** - * Removes the leading "::", if present, from a fully-scoped name. Sometimes - * CPPParser throws this on, and sometimes it doesn't. - */ -string InterrogateBuilder:: -descope(const string &name) { - if (name.length() >= 2 && name.substr(0, 2) == "::") { - return name.substr(2); - } - return name; -} - -/** - * Returns the FunctionIndex for the destructor appropriate to destruct an - * instance of the indicated type, or 0 if no suitable destructor exists. - */ -FunctionIndex InterrogateBuilder:: -get_destructor_for(CPPType *type) { - TypeIndex type_index = get_type(type, false); - - const InterrogateType &itype = - InterrogateDatabase::get_ptr()->get_type(type_index); - - return itype.get_destructor(); -} - -/** - * Returns the name of the type as it should be reported to the database. - * This is either the name indicated by the user via a renametype command, or - * the "preferred name" of the type itself (i.e. the typedef name within the - * C++ code), or failing that, the type's true name. - */ -string InterrogateBuilder:: -get_preferred_name(CPPType *type) { - string true_name = type->get_local_name(&parser); - string name = in_renametype(true_name); - if (!name.empty()) { - return name; - } - return type->get_preferred_name(); -} - -/** - * Hashes an arbitrary string into a four-character string using only the - * characters legal in a C identifier. - */ -string InterrogateBuilder:: -hash_string(const string &name, int shift_offset) { - unsigned int hash = 0; - - unsigned int shift = 0; - string::const_iterator ni; - for (ni = name.begin(); ni != name.end(); ++ni) { - unsigned int c = (unsigned char)*ni; - unsigned int shifted_c = (c << shift) & 0xffffff; - if (shift > 16) { - // We actually want a circular shift, not an arithmetic shift. - shifted_c |= ((c >> (24 - shift)) & 0xff) ; - } - hash = (hash + shifted_c) & 0xffffff; - shift = (shift + shift_offset) % 24; - } - - // Now multiply the hash by a biggish prime number and apply the high-order - // bits back at the bottom, to scramble up the bits a bit. This helps - // reduce hash conflicts from names that are similar to each other, by - // separating adjacent hash codes. - const unsigned int prime = 4999; - unsigned long long product = (unsigned long long)hash * prime; - hash = (product ^ (product >> 24)) & 0xffffff; - - // Also add in the additional_number, times some prime factor. hash = (hash - // + additional_number * 1657) & 0xffffff; - - // Now turn the hash code into a four-character string. For each six bits, - // we choose a character in the set [A-Za-z0-9_]. Note that there are only - // 63 characters to choose from; we have to duplicate '_' for values 62 and - // 63. This introduces a small additional chance of hash conflicts. No big - // deal, since we have to resolve hash conflicts anyway. - - string result; - for (int i = 0; i < 4; i++) { - unsigned int value = (hash & 0x3f); - hash >>= 6; - if (value < 26) { - result += (char)('A' + value); - - } else if (value < 52) { - result += (char)('a' + value - 26); - - } else if (value < 62) { - result += (char)('0' + value - 52); - - } else { - result += '_'; - } - } - - return result; -} - -/** - * Inserts a list of space-separated parameters into the given command - * parameter list. - */ -void InterrogateBuilder:: -insert_param_list(InterrogateBuilder::Commands &commands, - const string ¶ms) { - size_t p = 0; - while (p < params.length()) { - while (p < params.length() && isspace(params[p])) { - p++; - } - size_t q = p; - while (q < params.length() && !isspace(params[q])) { - q++; - } - if (p < q) { - commands.insert(params.substr(p, q - p)); - } - p = q; - } -} - -/** - * Returns true if the indicated name is one that the user identified with a - * forcetype command. - */ -bool InterrogateBuilder:: -in_forcetype(const string &name) const { - return (_forcetype.count(name) != 0); -} - -/** - * If the user requested an explicit name for this type via the renametype - * command, returns that name; otherwise, returns the empty string. - */ -string InterrogateBuilder:: -in_renametype(const string &name) const { - CommandParams::const_iterator pi; - pi = _renametype.find(name); - if (pi != _renametype.end()) { - return (*pi).second; - } - return string(); -} - -/** - * Returns true if the indicated name is one that the user identified with an - * ignoretype command. - */ -bool InterrogateBuilder:: -in_ignoretype(const string &name) const { - return (_ignoretype.count(name) != 0); -} - -/** - * If the user requested an explicit default constructor for this type via the - * defconstruct command, returns that string; otherwise, returns the empty - * string. - */ -string InterrogateBuilder:: -in_defconstruct(const string &name) const { - CommandParams::const_iterator pi; - pi = _defconstruct.find(name); - if (pi != _defconstruct.end()) { - return (*pi).second; - } - return string(); -} - -/** - * Returns true if the indicated name is one that the user identified with an - * ignoreinvolved command. - */ -bool InterrogateBuilder:: -in_ignoreinvolved(const string &name) const { - return (_ignoreinvolved.count(name) != 0); -} -/** - * Returns true if the indicated type involves some type name that the user - * identified with an ignoreinvolved command. - */ -bool InterrogateBuilder:: -in_ignoreinvolved(CPPType *type) const { - switch (type->get_subtype()) { - case CPPDeclaration::ST_pointer: - { - CPPPointerType *ptr = type->as_pointer_type(); - return in_ignoreinvolved(ptr->_pointing_at); - } - - case CPPDeclaration::ST_array: - { - CPPArrayType *ary = type->as_array_type(); - return in_ignoreinvolved(ary->_element_type); - } - - case CPPDeclaration::ST_reference: - { - CPPReferenceType *ref = type->as_reference_type(); - return in_ignoreinvolved(ref->_pointing_at); - } - - case CPPDeclaration::ST_const: - { - CPPConstType *cnst = type->as_const_type(); - return in_ignoreinvolved(cnst->_wrapped_around); - } - - case CPPDeclaration::ST_function: - { - CPPFunctionType *ftype = type->as_function_type(); - if (in_ignoreinvolved(ftype->_return_type)) { - return true; - } - const CPPParameterList::Parameters ¶ms = - ftype->_parameters->_parameters; - CPPParameterList::Parameters::const_iterator pi; - for (pi = params.begin(); pi != params.end(); ++pi) { - if (in_ignoreinvolved((*pi)->_type)) { - return true; - } - } - return false; - } - - case CPPDeclaration::ST_typedef: - { - if (in_ignoreinvolved(type->get_simple_name())) { - return true; - } - CPPTypedefType *tdef = type->as_typedef_type(); - return in_ignoreinvolved(tdef->_type); - } - - default: - return in_ignoreinvolved(type->get_simple_name()); - } -} - -/** - * Returns true if the indicated name is one that the user identified with an - * ignorefile command. - */ -bool InterrogateBuilder:: -in_ignorefile(const string &name) const { - return (_ignorefile.count(name) != 0); -} - -/** - * Returns true if the indicated name is one that the user identified with an - * ignoremember command. - */ -bool InterrogateBuilder:: -in_ignoremember(const string &name) const { - return (_ignoremember.count(name) != 0); -} - -/** - * Returns true if the indicated filename is one that the user identified with - * a noinclude command. - */ -bool InterrogateBuilder:: -in_noinclude(const string &name) const { - return (_noinclude.count(name) != 0); -} - -/** - * Returns true if the indicated filename is a valid file to explicitly - * #include in the generated .cxx file, false otherwise. - */ -bool InterrogateBuilder:: -should_include(const string &filename) const { - // Don't directly include any .cxx or .I files, except for extensions. - if (CPPFile::is_c_or_i_file(filename)) { - return false; - } - - // Also, don't include any files specifically forbidden in a .N file. - if (in_noinclude(filename)) { - return false; - } - - // Much as I hate to do it, I'm going to code in a special-case for two - // particularly nasty header files that we probably don't want to actually - // ever include. - if (filename == "winbase.h" || filename == "windows.h") { - return false; - } - - // Finally, don't include *_src.h or *_src.cxx. These are special - // "template" files that should not generally be included directly. - if (filename.length() > 6 && filename.substr(filename.length() - 6) == "_src.h") { - return false; - } - if (filename.length() > 8 && filename.substr(filename.length() - 8) == "_src.cxx") { - return false; - } - - // Ignore Objective-C files too. - if (filename.length() > 3 && filename.substr(filename.length() - 3) == ".mm") { - return false; - } - - // Otherwise, no problem. - return true; -} - -/** - * Recursively looks for the first inherited version of this function in the - * derivation chain of this class. Returns true if this function is declared - * published, or false if it is not published, or if it can't be found. - */ -bool InterrogateBuilder:: -is_inherited_published(CPPInstance *function, CPPStructType *struct_type) { - nassertr(struct_type->_derivation.size() == 1, false); - CPPStructType *base = struct_type->_derivation[0]._base->as_struct_type(); - nassertr(base != nullptr, false); - - CPPScope *base_scope = base->get_scope(); - CPPDeclaration *symbol = base_scope->find_symbol(function->get_simple_name(), true); - if (symbol == nullptr) { - // Couldn't find the inherited function. - return false; - } - - CPPFunctionGroup *fgroup = symbol->as_function_group(); - if (fgroup == nullptr) { - // Weird, it wasn't a function. - return false; - } - - CPPFunctionGroup::Instances::iterator ii; - for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) { - CPPInstance *inst = (*ii); - if (inst->_vis != V_published) { - // Some flavors of the method are not published. Take no chances. - return false; - } - } - // It appears that all flavors of the inherited method are published. - return true; -} - -/** - * Resequences all of the index numbers so that function wrappers start at 1 - * and occupy consecutive positions, and everything else follows. This allows - * us to build a table of function wrappers by index number. - * - * The "remaps" member is a list of FunctionRemap pointers. The collision in - * naming is unfortunate; the FunctionRemap objects are so named because they - * remap synthesized function wrappers to actual C++ methods and functions. - * It has nothing to do with the remapping of index numbers, which is the - * purpose of this function. - */ -void InterrogateBuilder:: -remap_indices(std::vector &remaps) { - IndexRemapper index_remap; - InterrogateDatabase::get_ptr()->remap_indices(1, index_remap); - - TypesByName::iterator ti; - for (ti = _types_by_name.begin(); ti != _types_by_name.end(); ++ti) { - (*ti).second = index_remap.map_from((*ti).second); - } - - FunctionsByName::iterator fi; - for (fi = _functions_by_name.begin(); - fi != _functions_by_name.end(); - ++fi) { - (*fi).second = index_remap.map_from((*fi).second); - } - - std::vector::iterator ri; - for (ri = remaps.begin(); ri != remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - remap->_wrapper_index = index_remap.map_from(remap->_wrapper_index); - } -} - -/** - * Adds the indicated global function to the database, if warranted. - */ -void InterrogateBuilder:: -scan_function(CPPFunctionGroup *fgroup) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - scan_function(function); - } -} - -/** - * Adds the indicated global function to the database, if warranted. - */ -void InterrogateBuilder:: -scan_function(CPPInstance *function) { - assert(function != nullptr); - assert(function->_type != nullptr && function->_type->as_function_type() != nullptr); - - CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type(); - assert(ftype != nullptr); - - CPPScope *scope = &parser; - if (function->is_scoped()) { - scope = function->get_scope(&parser, &parser); - if (scope == nullptr) { - // Invalid scope. - nout << "Invalid scope: " << *function->_ident << "\n"; - return; - } - - if (scope->get_struct_type() != nullptr) { - // Wait, this is a method, not a function. This must be the declaration - // for the method (since it's appearing out-of-scope). We don't need to - // define a new method for it, but we'd like to update the comment, if - // we have a comment. - update_function_comment(function, scope); - return; - } - } - - if (function->is_template()) { - // The function is a template function, not a true function. - return; - } - - if (function->_file.is_c_file()) { - // This function declaration appears in a .C file. We can only export - // functions whose prototypes appear in an .h file. - - string function_name = TypeManager::get_function_name(function); - - // Still, we can update the comment, at least. - update_function_comment(function, scope); - return; - } - - if (function->_file._source != CPPFile::S_local || - in_ignorefile(function->_file._filename_as_referenced)) { - // The function is defined in some other package or in an ignorable file. - return; - } - - if (function->_vis > min_vis) { - // The function is not marked to be exported. - return; - } - - if ((function->_storage_class & (CPPInstance::SC_static | CPPInstance::SC_deleted)) != 0) { - // The function is static or deleted, so can't be exported. - return; - } - - if (TypeManager::involves_protected(ftype)) { - // We can't export the function because it involves parameter types that - // are protected or private. - return; - } - - if (in_ignoreinvolved(ftype)) { - // The function or its parameters involves something that the user - // requested we ignore. - return; - } - - if (TypeManager::involves_rvalue_reference(ftype)) { - return; - } - - get_function(function, "", - nullptr, scope, - InterrogateFunction::F_global); -} - -/** - * Adds the indicated struct type to the database, if warranted. - */ -void InterrogateBuilder:: -scan_struct_type(CPPStructType *type) { - if (type == nullptr) { - return; - } - - if (type->is_template()) { - // The type is a template declaration, not a true type. - return; - } - - if (type->_file.is_c_file()) { - // This type declaration appears in a .C file. We can only export types - // defined in a .h file. - return; - } - - if (type->_file._source != CPPFile::S_local || - in_ignorefile(type->_file._filename_as_referenced)) { - // The type is defined in some other package or in an ignorable file. - return; - } - - // Check if any of the members are exported. If none of them are, and the - // type itself is not marked for export, then never mind. - if (type->_vis > min_vis) { - CPPScope *scope = type->_scope; - - bool any_exported = false; - CPPScope::Declarations::const_iterator di; - for (di = scope->_declarations.begin(); - di != scope->_declarations.end() && !any_exported; - ++di) { - if ((*di)->_vis <= min_vis) { - any_exported = true; - break; - } - } - - if (!any_exported) { - return; - } - } - - get_type(type, true); -} - -/** - * Adds the indicated enum type to the database, if warranted. - */ -void InterrogateBuilder:: -scan_enum_type(CPPEnumType *type) { - if (type == nullptr) { - return; - } - - if (type->is_template()) { - // The type is a template declaration, not a true type. - return; - } - - if (type->_file.is_c_file()) { - // This type declaration appears in a .C file. We can only export types - // defined in a .h file. - return; - } - - if (type->_file._source != CPPFile::S_local || - in_ignorefile(type->_file._filename_as_referenced)) { - // The type is defined in some other package or in an ignorable file. - return; - } - - if (type->_vis > min_vis) { - // The type is not marked to be exported. - return; - } - - get_type(type, true); -} - -/** - * Adds the indicated typedef type to the database, if warranted. - */ -void InterrogateBuilder:: -scan_typedef_type(CPPTypedefType *type) { - if (type == nullptr) { - return; - } - - if (type->is_template()) { - // The type is a template declaration, not a true type. - return; - } - - if (type->_file.is_c_file()) { - // This type declaration appears in a .C file. We can only export types - // defined in a .h file. - return; - } - - if (type->_file._source != CPPFile::S_local || - in_ignorefile(type->_file._filename_as_referenced)) { - // The type is defined in some other package or in an ignorable file. - return; - } - -/* - * Do we require explicitly placing BEGIN_PUBLISHEND_PUBLISH blocks around - * typedefs for them to be exported? My thinking is that we shoudn't, for - * now, since we don't require it for structs either (we only require it to - * have published methods). if (type->_vis > min_vis) { The wrapped type is - * not marked to be exported. return; } - */ - - // Find out what this typedef points to. - CPPType *wrapped_type = type->_type; - bool forced = in_forcetype(wrapped_type->get_local_name(&parser)); - - while (wrapped_type->get_subtype() == CPPDeclaration::ST_typedef) { - wrapped_type = wrapped_type->as_typedef_type()->_type; - forced = forced || in_forcetype(wrapped_type->get_local_name(&parser)); - } - - CPPStructType *struct_type = wrapped_type->as_struct_type(); - if (struct_type == nullptr) { - // We only export typedefs to structs, for now. - return; - } - - // Always export typedefs pointing to forced types. - if (!forced) { - if (wrapped_type->_file._source != CPPFile::S_local || - in_ignorefile(wrapped_type->_file._filename_as_referenced)) { - // The wrapped type is defined in some other package or in an ignorable - // file. - return; - } - - // Check if any of the wrapped type's members are published. If none of - // them are, and the wrapped type itself is not marked for export, then - // never mind. - if (struct_type->_vis > min_vis) { - CPPScope *scope = struct_type->_scope; - - bool any_exported = false; - CPPScope::Declarations::const_iterator di; - for (di = scope->_declarations.begin(); - di != scope->_declarations.end() && !any_exported; - ++di) { - if ((*di)->_vis <= min_vis) { - any_exported = true; - break; - } - } - - if (!any_exported) { - return; - } - } - } - - get_type(type, true); -} - -/** - * Adds the indicated manifest constant to the database, if warranted. - */ -void InterrogateBuilder:: -scan_manifest(CPPManifest *manifest) { - if (manifest == nullptr) { - return; - } - - if (manifest->_loc.file.is_c_file()) { - // This #define appears in a .C file. We can only export manifests - // defined in a .h file. - return; - } - - if (manifest->_loc.file._source != CPPFile::S_local || - in_ignorefile(manifest->_loc.file._filename_as_referenced)) { - // The manifest is defined in some other package or in an ignorable file. - return; - } - - if (manifest->_vis > min_vis) { - // The manifest is not marked for export. - return; - } - - if (manifest->_has_parameters) { - // We can't export manifest functions. - return; - } - - InterrogateManifest imanifest; - imanifest._name = manifest->_name; - imanifest._definition = manifest->expand(); - - CPPType *type = manifest->determine_type(); - if (type != nullptr) { - imanifest._flags |= InterrogateManifest::F_has_type; - imanifest._type = get_type(type, false); - - CPPExpression *expr = manifest->_expr; - CPPExpression::Result result = expr->evaluate(); - if (result._type == CPPExpression::RT_integer) { - // We have an integer-valued expression. - imanifest._flags |= InterrogateManifest::F_has_int_value; - imanifest._int_value = result.as_integer(); - - } else { - // We have a more complex expression. Generate a getter function. - FunctionIndex getter = - get_getter(type, manifest->_name, nullptr, &parser, - nullptr); - - if (getter != 0) { - imanifest._flags |= InterrogateManifest::F_has_getter; - imanifest._getter = getter; - } - } - } - - ManifestIndex index = - InterrogateDatabase::get_ptr()->get_next_index(); - InterrogateDatabase::get_ptr()->add_manifest(index, imanifest); -} - -/** - * Adds the indicated data element to the database, if warranted. - */ -ElementIndex InterrogateBuilder:: -scan_element(CPPInstance *element, CPPStructType *struct_type, - CPPScope *scope) { - if (element == nullptr) { - return 0; - } - - if (element->is_template()) { - // The element is a template element, not a true element. - return 0; - } - - if (element->is_scoped()) { - if (element->get_scope(scope, &parser) != scope) { - // This is an element defined out-of-scope. It's probably the - // definition for a data member. Ignore it. - return 0; - } - } - - if (element->_file.is_c_file()) { - // This element declaration appears in a .C file. We can only export - // elements declared in a .h file. - return 0; - } - - if (struct_type == nullptr && - (element->_file._source != CPPFile::S_local || - in_ignorefile(element->_file._filename_as_referenced))) { - // The element is defined in some other package or in an ignorable file. - return 0; - } - - if (element->_vis > min_vis) { - // The element is not marked for export. - return 0; - } - - if ((element->_storage_class & CPPInstance::SC_static) != 0) { - // The element is static, so can't be exported. - return 0; - } - - // Make sure the element knows what its scope is. - if (element->_ident->_native_scope != scope) { - element = new CPPInstance(*element); - element->_ident = new CPPIdentifier(*element->_ident); - element->_ident->_native_scope = scope; - } - - CPPType *element_type = TypeManager::resolve_type(element->_type, scope); - CPPType *parameter_type = element_type; - - InterrogateElement ielement; - ielement._name = element->get_local_name(scope); - ielement._scoped_name = descope(element->get_local_name(&parser)); - - // See if there happens to be a comment before the element. - if (element->_leading_comment != nullptr) { - ielement._comment = trim_blanks(element->_leading_comment->_comment); - } - - ielement._type = get_type(TypeManager::unwrap_reference(element_type), false); - if (ielement._type == 0) { - // If we can't understand what type it is, forget it. - return 0; - } - - if (!TypeManager::involves_protected(element_type)) { - // We can only generate a getter and a setter if we can talk about the - // type it is. - - if (parameter_type->as_struct_type() != nullptr && - !parameter_type->is_trivial()) { - // Wrap the type in a const reference. - parameter_type = TypeManager::wrap_const_reference(parameter_type); - } - - // Generate a getter and setter function for the element. - FunctionIndex getter = - get_getter(parameter_type, element->get_local_name(scope), - struct_type, scope, element); - if (getter != 0) { - ielement._flags |= InterrogateElement::F_has_getter; - ielement._getter = getter; - } - - if (TypeManager::is_assignable(element_type)) { - FunctionIndex setter = - get_setter(parameter_type, element->get_local_name(scope), - struct_type, scope, element); - if (setter != 0) { - ielement._flags |= InterrogateElement::F_has_setter; - ielement._setter = setter; - } - } - } - - if (struct_type == nullptr) { - // This is a global data element: not a data member. - ielement._flags |= InterrogateElement::F_global; - } - - ElementIndex index = - InterrogateDatabase::get_ptr()->get_next_index(); - InterrogateDatabase::get_ptr()->add_element(index, ielement); - - return index; -} - -/** - * Adds a function to return the value for the indicated expression. Returns - * the new function index. - */ -FunctionIndex InterrogateBuilder:: -get_getter(CPPType *expr_type, string expression, - CPPStructType *struct_type, CPPScope *scope, - CPPInstance *element) { - // Make up a name for the function. - string fname = clean_identifier("get_" + expression); - - // Unroll the "const" from the expr_type, since that doesn't matter for a - // return type. - while (expr_type->as_const_type() != nullptr) { - expr_type = expr_type->as_const_type()->_wrapped_around; - assert(expr_type != nullptr); - } - - // We can't return an array from a function, but we can decay it into a - // pointer. - while (expr_type->get_subtype() == CPPDeclaration::ST_array) { - expr_type = CPPType::new_type(new CPPPointerType(expr_type->as_array_type()->_element_type)); - } - - // Make up a CPPFunctionType. - CPPParameterList *params = new CPPParameterList; - CPPFunctionType *ftype = new CPPFunctionType(expr_type, params, 0); - - // Now make up an instance for the function. - CPPInstance *function = new CPPInstance(ftype, fname); - function->_ident->_native_scope = scope; - - int getter_flags = InterrogateFunction::F_getter; - - if (struct_type != nullptr) { - // This is a data member for some class. - assert(element != nullptr); - assert(scope != nullptr); - - if ((element->_storage_class & CPPInstance::SC_static) != 0) { - // This is a static data member; therefore, the synthesized getter is - // also static. - function->_storage_class |= CPPInstance::SC_static; - - // And the expression is fully scoped. - expression = element->get_local_name(&parser); - - } else { - // This is a non-static data member, so it has a const synthesized - // getter method. - ftype->_flags |= CPPFunctionType::F_const_method; - - // And the expression is locally scoped. - expression = element->get_local_name(scope); - getter_flags |= InterrogateFunction::F_method; - } - } - - // Now check to see if there's already a function matching this name. If - // there is, we can't define a getter, and we shouldn't mistake this other - // function for a synthesized getter. - string function_name = TypeManager::get_function_name(function); - if (_functions_by_name.count(function_name) != 0) { - return 0; - } - - ostringstream desc; - desc << "getter for "; - if (element != nullptr) { - element->_initializer = nullptr; - element->output(desc, 0, &parser, false); - desc << ";"; - } else { - desc << expression; - } - string description = desc.str(); - - // It's clear; make a getter. - FunctionIndex index = - get_function(function, description, - struct_type, scope, - getter_flags, expression); - - InterrogateDatabase::get_ptr()->update_function(index)._comment = description; - return index; -} - -/** - * Adds a function to return the value for the indicated expression. Returns - * the new function index. - */ -FunctionIndex InterrogateBuilder:: -get_setter(CPPType *expr_type, string expression, - CPPStructType *struct_type, CPPScope *scope, - CPPInstance *element) { - // Make up a name for the function. - string fname = clean_identifier("set_" + expression); - - // Make up a CPPFunctionType. - CPPParameterList *params = new CPPParameterList; - CPPInstance *param0 = new CPPInstance(expr_type, "value"); - params->_parameters.push_back(param0); - CPPType *void_type = TypeManager::get_void_type(); - CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0); - - // Now make up an instance for the function. - CPPInstance *function = new CPPInstance(ftype, fname); - function->_ident->_native_scope = scope; - - int setter_flags = InterrogateFunction::F_setter; - - if (struct_type != nullptr) { - // This is a data member for some class. - assert(element != nullptr); - assert(scope != nullptr); - - if ((element->_storage_class & CPPInstance::SC_static) != 0) { - // This is a static data member; therefore, the synthesized setter is - // also static. - function->_storage_class |= CPPInstance::SC_static; - - // And the expression is fully scoped. - expression = element->get_local_name(&parser); - - } else { - // This is a non-static data member. The expression is locally scoped. - expression = element->get_local_name(scope); - setter_flags |= InterrogateFunction::F_method; - } - } - - // Now check to see if there's already a function matching this name. If - // there is, we can't define a setter, and we shouldn't mistake this other - // function for a synthesized setter. - string function_name = TypeManager::get_function_name(function); - if (_functions_by_name.count(function_name) != 0) { - return 0; - } - - ostringstream desc; - desc << "setter for "; - if (element != nullptr) { - element->_initializer = nullptr; - element->output(desc, 0, &parser, false); - desc << ";"; - } else { - desc << expression; - } - string description = desc.str(); - - // It's clear; make a setter. - FunctionIndex index = - get_function(function, description, - struct_type, scope, - setter_flags, expression); - - InterrogateDatabase::get_ptr()->update_function(index)._comment = description; - return index; -} - -/** - * Adds a function to cast from a pointer of the indicated type to a pointer - * of the indicated type to the database. Returns the new function index. - */ -FunctionIndex InterrogateBuilder:: -get_cast_function(CPPType *to_type, CPPType *from_type, - const string &prefix) { - CPPInstance *function; - CPPStructType *struct_type = from_type->as_struct_type(); - CPPScope *scope = &parser; - - if (struct_type != nullptr) { - // We'll make this a method of the from type. - scope = struct_type->get_scope(); - - // Make up a name for the method. - string fname = - clean_identifier(prefix + "_to_" + get_preferred_name(to_type)); - - // Make up a CPPFunctionType. - CPPType *to_ptr_type = CPPType::new_type(new CPPPointerType(to_type)); - - CPPParameterList *params = new CPPParameterList; - CPPFunctionType *ftype = new CPPFunctionType(to_ptr_type, params, 0); - - // Now make up an instance for the function. - function = new CPPInstance(ftype, fname); - - } else { - // The from type isn't a struct or a class, so this has to be an external - // function. - - // Make up a name for the function. - string fname = - clean_identifier(prefix + "_" + get_preferred_name(from_type) + - "_to_" + get_preferred_name(to_type)); - - // Make up a CPPFunctionType. - CPPType *from_ptr_type = CPPType::new_type(new CPPPointerType(from_type)); - CPPType *to_ptr_type = CPPType::new_type(new CPPPointerType(to_type)); - - CPPInstance *param0 = new CPPInstance(from_ptr_type, "this"); - CPPParameterList *params = new CPPParameterList; - params->_parameters.push_back(param0); - CPPFunctionType *ftype = new CPPFunctionType(to_ptr_type, params, 0); - - // Now make up an instance for the function. - function = new CPPInstance(ftype, fname); - } - - ostringstream desc; - desc << prefix << " from " << *from_type << " to " << *to_type; - string description = desc.str(); - - FunctionIndex index = - get_function(function, description, - struct_type, scope, - InterrogateFunction::F_typecast); - - InterrogateDatabase::get_ptr()->update_function(index)._comment = description; - return index; -} - -/** - * Adds the indicated function to the database, if it is not already present. - * In either case, returns the FunctionIndex of the function within the - * database. - */ -FunctionIndex InterrogateBuilder:: -get_function(CPPInstance *function, string description, - CPPStructType *struct_type, - CPPScope *scope, int flags, - const string &expression) { - - // Get a unique function signature. Make sure we tell the function where - // its native scope is, so we get a fully-scoped signature. - - if (function->_ident->_native_scope != scope) { - function = new CPPInstance(*function); - function->_ident = new CPPIdentifier(*function->_ident); - function->_ident->_native_scope = scope; - } - CPPFunctionType *ftype = - function->_type->resolve_type(scope, &parser)->as_function_type(); - function->_type = ftype; - - if ((ftype->_flags & CPPFunctionType::F_constructor) && - struct_type != nullptr && - struct_type->is_abstract()) { - // This is a constructor for an abstract class; forget it. - return 0; - } - - TypeIndex class_index = 0; - if (struct_type != nullptr) { - class_index = get_type(struct_type, false); - } - - string function_name = TypeManager::get_function_name(function); - string function_signature = TypeManager::get_function_signature(function); - - if (ftype->_flags & CPPFunctionType::F_unary_op) { - // This is a unary operator function. Name it differently so we don't - // consider it an overloaded version of a similarly-named binary operator. - function_name += "unary"; - } - - // First, check to see if it's already there. - FunctionsByName::const_iterator tni = - _functions_by_name.find(function_name); - if (tni != _functions_by_name.end()) { - FunctionIndex index = (*tni).second; - - // It's already here, so update the flags. - InterrogateFunction &ifunction = - InterrogateDatabase::get_ptr()->update_function(index); - - ifunction._flags |= flags; - - // Also, make sure this particular signature is defined. - std::pair result = - ifunction._instances->insert(InterrogateFunction::Instances::value_type(function_signature, function)); - - InterrogateFunction::Instances::iterator ii = result.first; - bool inserted = result.second; - - if (inserted) { - // If we just added the new signature, append the prototype. - ostringstream prototype; - function->output(prototype, 0, &parser, false); - prototype << ";"; - ifunction._prototype += "\n" + prototype.str(); - } - - // Also set the comment. - if (function->_leading_comment != nullptr) { - string comment = trim_blanks(function->_leading_comment->_comment); - if (!ifunction._comment.empty()) { - ifunction._comment += "\n\n"; - } - ifunction._comment += comment; - - // And update the particular wrapper comment. - if ((*ii).second->_leading_comment == nullptr || - function->_leading_comment->_comment.length() > - (*ii).second->_leading_comment->_comment.length()) { - (*ii).second->_leading_comment = function->_leading_comment; - } - } - - return index; - } - - // It isn't here, so we'll have to define it. - FunctionIndex index = - InterrogateDatabase::get_ptr()->get_next_index(); - _functions_by_name[function_name] = index; - - InterrogateFunction *ifunction = new InterrogateFunction; - ifunction->_name = function->get_local_name(scope); - ifunction->_scoped_name = descope(function->get_local_name(&parser)); - ifunction->_instances = new InterrogateFunction::Instances; - - if (function->_leading_comment != nullptr) { - ifunction->_comment = trim_blanks(function->_leading_comment->_comment); - } - - ostringstream prototype; - function->output(prototype, 0, &parser, false); - prototype << ";"; - ifunction->_prototype = prototype.str(); - - if (struct_type != nullptr) { - // The function is a method. - ifunction->_flags |= InterrogateFunction::F_method; - ifunction->_class = class_index; - } - - if (ftype->_flags & CPPFunctionType::F_unary_op) { - // This is a special unary function. - ifunction->_flags |= InterrogateFunction::F_unary_op; - } - - if (ftype->_flags & CPPFunctionType::F_operator_typecast) { - // This is a special typecast operator. - ifunction->_flags |= InterrogateFunction::F_operator_typecast; - } - - if (ftype->_flags & CPPFunctionType::F_constructor) { - // This is a constructor. - ifunction->_flags |= InterrogateFunction::F_constructor; - } - - if (ftype->_flags & CPPFunctionType::F_destructor) { - // This is a destructor. - ifunction->_flags |= InterrogateFunction::F_destructor; - } - - if (function->_storage_class & CPPInstance::SC_virtual) { - // This is a virtual function. - ifunction->_flags |= InterrogateFunction::F_virtual; - } - - ifunction->_flags |= flags; - ifunction->_instances->insert(InterrogateFunction::Instances::value_type(function_signature, function)); - ifunction->_expression = expression; - - InterrogateDatabase::get_ptr()->add_function(index, ifunction); - - return index; -} - -/** - * Adds the indicated make_property or make_seq_property to the database, if - * it is not already present. In either case, returns the ElementIndex - * of the created property within the database. - */ -ElementIndex InterrogateBuilder:: -get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CPPScope *scope) { - // This is needed so we can get a proper unique name for the property. - if (make_property->_ident->_native_scope != scope) { - make_property = new CPPMakeProperty(*make_property); - make_property->_ident = new CPPIdentifier(*make_property->_ident); - make_property->_ident->_native_scope = scope; - } - - string property_name = make_property->get_local_name(&parser); - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - - // First, check to see if it's already there. - ElementIndex index = 0; - PropertiesByName::const_iterator tni = - _properties_by_name.find(property_name); - if (tni != _properties_by_name.end()) { - index = (*tni).second; - const InterrogateElement &ielem = idb->get_element(index); - if (ielem._make_property == make_property) { - // This is the same property. - return index; - } - - // It is possible to have property definitions with the same name, but - // they cannot define conflicting interfaces. - if ((ielem.is_sequence() || ielem.is_mapping()) != - (make_property->_type != CPPMakeProperty::T_normal)) { - cerr << "Conflicting property definitions for " << property_name << "!\n"; - return index; - } - } - - // If we have a length function (ie. this is a sequence property), we should - // find the function that will give us the length. - FunctionIndex length_function = 0; - CPPFunctionGroup *fgroup = make_property->_length_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = function->_type->as_function_type(); - if (ftype != nullptr) { - length_function = get_function(function, "", struct_type, - struct_type->get_scope(), 0); - if (length_function != 0) { - break; - } - } - } - if (length_function == 0) { - cerr << "No instance of length method '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } - - // Find the getter so we can get its return type. - CPPInstance *getter = nullptr; - CPPType *return_type = nullptr; - - // How many arguments we expect the getter to have. - size_t num_args = (size_t)(make_property->_type != CPPMakeProperty::T_normal); - - fgroup = make_property->_get_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = function->_type->as_function_type(); - if (ftype == nullptr) { - continue; - } - - const CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters; - - size_t expected_num_args = 0; - size_t index_arg = 0; - - if (make_property->_type != CPPMakeProperty::T_normal) { - ++expected_num_args; - } - - if (!params.empty() && params[0]->get_simple_name() == "self" && - TypeManager::is_pointer_to_PyObject(params[0]->_type)) { - // Taking a PyObject *self argument. - expected_num_args += 1; - index_arg += 1; - } - - // The getter must either take no arguments, or all defaults. - if (params.size() == expected_num_args || - (params.size() > expected_num_args && - params[expected_num_args]->_initializer != nullptr)) { - // If this is a sequence getter, it must take an index argument. - if (make_property->_type == CPPMakeProperty::T_sequence && - !TypeManager::is_integer(params[index_arg]->_type)) { - continue; - } - - getter = function; - return_type = ftype->_return_type; - - // The return type of the non-const method probably better represents - // the type of the property we are creating. - if ((ftype->_flags & CPPFunctionType::F_const_method) == 0) { - break; - } - } - } - - if (getter == nullptr || return_type == nullptr) { - cerr << "No instance of getter '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } - - // Find the "hasser". - CPPInstance *hasser = nullptr; - - fgroup = make_property->_has_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = - function->_type->as_function_type(); - if (ftype != nullptr && (TypeManager::is_integer(ftype->_return_type) || - TypeManager::is_pointer(ftype->_return_type))) { - hasser = function; - break; - } - } - - if (hasser == nullptr) { - cerr << "No instance of has-function '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } - - // And the "deleter". - CPPInstance *deleter = nullptr; - - fgroup = make_property->_del_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = function->_type->as_function_type(); - if (ftype != nullptr) { - const CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters; - if (params.size() == num_args || - (params.size() > num_args && params[num_args]->_initializer != nullptr)) { - deleter = function; - break; - } - } - } - - if (deleter == nullptr) { - cerr << "No instance of delete-function '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } - - // And the "inserter". - CPPInstance *inserter = nullptr; - - fgroup = make_property->_insert_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = function->_type->as_function_type(); - if (ftype != nullptr && ftype->_parameters->_parameters.size() == 2) { - inserter = function; - break; - } - } - - if (inserter == nullptr) { - cerr << "No instance of insert-function '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } - - // And the function that returns a key by index. - CPPInstance *getkey_function = nullptr; - - fgroup = make_property->_get_key_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = function->_type->as_function_type(); - if (ftype != nullptr) { - getkey_function = function; - break; - } - } - - if (getkey_function == nullptr) { - cerr << "No instance of get-key-function '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } - - if (index == 0) { - // It isn't here, so we'll have to define it. - index = idb->get_next_index(); - _properties_by_name[property_name] = index; - - InterrogateElement iproperty; - iproperty._name = make_property->get_simple_name(); - iproperty._scoped_name = descope(make_property->get_local_name(&parser)); - idb->add_element(index, iproperty); - } - - InterrogateElement &iproperty = idb->update_element(index); - - if (return_type != nullptr) { - TypeIndex return_index = get_type(TypeManager::unwrap_reference(return_type), false); - if (iproperty._type != 0 && iproperty._type != return_index) { - cerr << "Property " << property_name << " has inconsistent element type!\n"; - } - iproperty._type = return_index; - } else { - iproperty._type = 0; - } - - if (make_property->_type & CPPMakeProperty::T_sequence) { - iproperty._flags |= InterrogateElement::F_sequence; - iproperty._length_function = length_function; - assert(length_function != 0); - } - - if (make_property->_type & CPPMakeProperty::T_mapping) { - iproperty._flags |= InterrogateElement::F_mapping; - iproperty._length_function = length_function; - } - - if (getter != nullptr) { - iproperty._flags |= InterrogateElement::F_has_getter; - iproperty._getter = get_function(getter, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._getter, 0); - } - - if (hasser != nullptr) { - iproperty._flags |= InterrogateElement::F_has_has_function; - iproperty._has_function = get_function(hasser, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._has_function, 0); - } - - if (deleter != nullptr) { - iproperty._flags |= InterrogateElement::F_has_del_function; - iproperty._del_function = get_function(deleter, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._del_function, 0); - } - - if (inserter != nullptr) { - iproperty._flags |= InterrogateElement::F_has_insert_function; - iproperty._insert_function = get_function(inserter, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._insert_function, 0); - } - - if (getkey_function != nullptr) { - iproperty._flags |= InterrogateElement::F_has_getkey_function; - iproperty._getkey_function = get_function(getkey_function, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._getkey_function, 0); - } - - // See if there happens to be a comment before the MAKE_PROPERTY macro. - if (make_property->_leading_comment != nullptr) { - iproperty._comment = trim_blanks(make_property->_leading_comment->_comment); - - } else if (getter->_leading_comment != nullptr) { - // Take the comment from the getter. - iproperty._comment = trim_blanks(getter->_leading_comment->_comment); - } - - // Now look for setters. - fgroup = make_property->_set_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - iproperty._flags |= InterrogateElement::F_has_setter; - iproperty._setter = get_function(function, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._setter, 0); - break; - } - } - - fgroup = make_property->_clear_function; - if (fgroup != nullptr) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - iproperty._flags |= InterrogateElement::F_has_clear_function; - iproperty._clear_function = get_function(function, "", struct_type, - struct_type->get_scope(), 0); - nassertr(iproperty._clear_function, 0); - break; - } - } - - return index; -} - -/** - * Adds the indicated make_seq to the database, if it is not already present. - * In either case, returns the MakeSeq of the make_seq within the database. - */ -MakeSeqIndex InterrogateBuilder:: -get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type) { - string make_seq_name = make_seq->get_local_name(&parser); - - // First, check to see if it's already there. - MakeSeqsByName::const_iterator tni = - _make_seqs_by_name.find(make_seq_name); - if (tni != _make_seqs_by_name.end()) { - MakeSeqIndex index = (*tni).second; - return index; - } - - FunctionIndex length_getter = 0; - FunctionIndex element_getter = 0; - - CPPFunctionGroup::Instances::const_iterator fi; - CPPFunctionGroup *fgroup = make_seq->_length_getter; - if (fgroup != nullptr) { - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = - function->_type->as_function_type(); - if (ftype != nullptr) { - length_getter = get_function(function, "", struct_type, - struct_type->get_scope(), 0); - if (length_getter != 0) { - break; - } - } - } - if (length_getter == 0) { - cerr << "No instance of length method '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } else { - cerr << "MAKE_SEQ " << make_seq_name << " requires a length method.\n"; - return 0; - } - - fgroup = make_seq->_element_getter; - if (fgroup != nullptr) { - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - CPPFunctionType *ftype = - function->_type->as_function_type(); - if (ftype != nullptr && ftype->_parameters->_parameters.size() >= 1 && - TypeManager::is_integer(ftype->_parameters->_parameters[0]->_type)) { - // It really doesn't matter whether we grab the const or non-const - // version, since they should all return the same function anyway. - element_getter = get_function(function, "", struct_type, - struct_type->get_scope(), 0); - if (element_getter != 0) { - break; - } - } - } - if (element_getter == 0) { - cerr << "No instance of element method '" - << fgroup->_name << "' is suitable!\n"; - return 0; - } - } else { - cerr << "MAKE_SEQ " << make_seq_name << " requires an element method.\n"; - return 0; - } - - InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); - // It isn't here, so we'll have to define it. - MakeSeqIndex index = idb->get_next_index(); - _make_seqs_by_name[make_seq_name] = index; - - InterrogateMakeSeq imake_seq; - imake_seq._name = make_seq->get_simple_name(); - imake_seq._scoped_name = descope(make_seq->get_local_name(&parser)); - - imake_seq._length_getter = length_getter; - imake_seq._element_getter = element_getter; - - // See if there happens to be a comment before the MAKE_SEQ macro. - if (make_seq->_leading_comment != nullptr) { - imake_seq._comment = trim_blanks(make_seq->_leading_comment->_comment); - } - - idb->add_make_seq(index, imake_seq); - - return index; -} - -/** - * Returns a TypeIndex for the "atomic string" type, which is a bogus type - * that might be used if -string is passed to interrogate. It means to - * translate basic_string and char * to whatever atomic string type is - * native to the particular the scripting language we happen to be generating - * wrappers for. - */ -TypeIndex InterrogateBuilder:: -get_atomic_string_type() { - // Make up a true name that can't possibly clash with an actual C++ type - // name. - string true_name = "atomic string"; - - TypesByName::const_iterator tni = _types_by_name.find(true_name); - if (tni != _types_by_name.end()) { - return (*tni).second; - } - - // This is the first time the atomic string has been requested; define it - // now. - - TypeIndex index = InterrogateDatabase::get_ptr()->get_next_index(); - _types_by_name[true_name] = index; - - InterrogateType itype; - itype._flags |= InterrogateType::F_atomic; - itype._atomic_token = AT_string; - itype._true_name = true_name; - itype._scoped_name = true_name; - itype._name = true_name; - - InterrogateDatabase::get_ptr()->add_type(index, itype); - - return index; -} - -/** - * Adds the indicated type to the database, if it is not already present. In - * either case, returns the TypeIndex of the type within the database. - */ -TypeIndex InterrogateBuilder:: -get_type(CPPType *type, bool global) { - if (type->is_template()) { - // Can't do anything with a template type. - return 0; - } - - if (type->get_subtype() == CPPType::ST_tbd) { - type = type->resolve_type(&parser, &parser); - } - - TypeIndex index = 0; - - // First, check to see if it's already there. - string true_name = type->get_local_name(&parser); - - if (true_name.empty()) { - // Whoops, it's an anonymous type. That's okay, because we'll usually - // only encounter them once anyway, so let's go ahead and define it - // without checking _types_by_name first. - - } else { - TypesByName::const_iterator tni = _types_by_name.find(true_name); - if (tni != _types_by_name.end()) { - // It's already here, so update the global flag. - index = (*tni).second; - if (index == 0) { - // This is an invalid type; we don't know anything about it. - return 0; - } - - InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index); - if (global) { - itype._flags |= InterrogateType::F_global; - } - - if ((itype._flags & InterrogateType::F_fully_defined) != 0) { - return index; - } - - // But wait--it's not fully defined yet! We'll go ahead and define it - // now. - } - } - - bool forced = in_forcetype(true_name); - - if (index == 0) { - // It isn't already there, so we have to define it. - index = InterrogateDatabase::get_ptr()->get_next_index(); - if (!true_name.empty()) { - _types_by_name[true_name] = index; - } - - InterrogateType itype; - if (global) { - itype._flags |= InterrogateType::F_global; - } - - InterrogateDatabase::get_ptr()->add_type(index, itype); - } - - InterrogateType &itype = - InterrogateDatabase::get_ptr()->update_type(index); - - itype._name = get_preferred_name(type); - - int num_alt_names = type->get_num_alt_names(); - if (num_alt_names != 0) { - itype._alt_names.clear(); - for (int i = 0; i < num_alt_names; ++i) { - string alt_name = type->get_alt_name(i); - itype._alt_names.push_back(alt_name); - } - } - - itype._scoped_name = true_name; - itype._true_name = true_name; - itype._cpptype = type; - - if (type->_declaration != nullptr) { - // This type has a declaration; does the declaration have a comment? - CPPTypeDeclaration *decl = type->_declaration; - if (decl->_leading_comment != nullptr) { - itype._comment = trim_blanks(decl->_leading_comment->_comment); - } - } - - CPPScope *scope = nullptr; - // If it's an extension type or typedef, it might be scoped. - if (CPPTypedefType *td_type = type->as_typedef_type()) { - scope = td_type->_ident->get_scope(&parser, &parser); - - } else if (CPPExtensionType *ext_type = type->as_extension_type()) { - if (ext_type->_ident != nullptr) { - scope = ext_type->_ident->get_scope(&parser, &parser); - - } else if (CPPEnumType *enum_type = ext_type->as_enum_type()) { - // Special case for anonymous enums. - scope = enum_type->_parent_scope; - } - - } - - if (scope != nullptr) { - while (scope->as_template_scope() != nullptr) { - assert(scope->get_parent_scope() != scope); - scope = scope->get_parent_scope(); - assert(scope != nullptr); - } - itype._cppscope = scope; - - if (scope != &parser) { - // We're scoped! - itype._scoped_name = - descope(scope->get_local_name(&parser) + "::" + itype._name); - CPPStructType *struct_type = scope->get_struct_type(); - - if (struct_type != nullptr) { - itype._flags |= InterrogateType::F_nested; - itype._outer_class = get_type(struct_type, false); - } - } - } - - if (type->_attributes.has_attribute("deprecated")) { - itype._flags |= InterrogateType::F_deprecated; - } - - if (forced || !in_ignoretype(true_name)) { - itype._flags |= InterrogateType::F_fully_defined; - - if (type->as_simple_type() != nullptr) { - define_atomic_type(itype, type->as_simple_type()); - - } else if (type->as_pointer_type() != nullptr) { - define_wrapped_type(itype, type->as_pointer_type()); - - } else if (type->as_const_type() != nullptr) { - define_wrapped_type(itype, type->as_const_type()); - - } else if (type->as_struct_type() != nullptr) { - define_struct_type(itype, type->as_struct_type(), index, forced); - - } else if (type->as_enum_type() != nullptr) { - define_enum_type(itype, type->as_enum_type()); - - } else if (type->as_extension_type() != nullptr) { - define_extension_type(itype, type->as_extension_type()); - - } else if (type->as_typedef_type() != nullptr) { - define_typedef_type(itype, type->as_typedef_type()); - - } else if (type->as_array_type() != nullptr) { - define_array_type(itype, type->as_array_type()); - - } else { - nout << "Attempt to define invalid type " << *type - << " (subtype " << type->get_subtype() << ")\n"; - - // Remove the type from the database. - InterrogateDatabase::get_ptr()->remove_type(index); - if (!true_name.empty()) { - _types_by_name[true_name] = 0; - } - index = 0; - } - } - - return index; -} - -/** - * Builds up a definition for the indicated atomic type. - */ -void InterrogateBuilder:: -define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) { - itype._flags |= InterrogateType::F_atomic; - - switch (cpptype->_type) { - case CPPSimpleType::T_bool: - itype._atomic_token = AT_bool; - break; - - case CPPSimpleType::T_char: - itype._atomic_token = AT_char; - break; - - case CPPSimpleType::T_wchar_t: - itype._atomic_token = AT_int; - break; - - case CPPSimpleType::T_char8_t: - itype._flags |= InterrogateType::F_unsigned; - itype._atomic_token = AT_int; - break; - - case CPPSimpleType::T_char16_t: - itype._flags |= InterrogateType::F_unsigned; - itype._atomic_token = AT_int; - break; - - case CPPSimpleType::T_char32_t: - itype._flags |= InterrogateType::F_unsigned; - itype._atomic_token = AT_int; - break; - - case CPPSimpleType::T_int: - if ((cpptype->_flags & CPPSimpleType::F_longlong) != 0) { - itype._atomic_token = AT_longlong; - } else { - itype._atomic_token = AT_int; - } - break; - - case CPPSimpleType::T_float: - itype._atomic_token = AT_float; - break; - - case CPPSimpleType::T_double: - itype._atomic_token = AT_double; - break; - - case CPPSimpleType::T_void: - itype._atomic_token = AT_void; - break; - - case CPPSimpleType::T_nullptr: - itype._atomic_token = AT_null; - break; - - default: - nout << "Type \"" << *cpptype << "\" has invalid CPPSimpleType: " - << (int)cpptype->_type << "\n"; - itype._atomic_token = AT_not_atomic; - } - - if ((cpptype->_flags & CPPSimpleType::F_longlong) != 0) { - itype._flags |= InterrogateType::F_longlong; - - } else if ((cpptype->_flags & CPPSimpleType::F_long) != 0) { - itype._flags |= InterrogateType::F_long; - } - - if ((cpptype->_flags & CPPSimpleType::F_short) != 0) { - itype._flags |= InterrogateType::F_short; - } - if ((cpptype->_flags & CPPSimpleType::F_unsigned) != 0) { - itype._flags |= InterrogateType::F_unsigned; - } - if ((cpptype->_flags & CPPSimpleType::F_signed) != 0) { - itype._flags |= InterrogateType::F_signed; - } -} - -/** - * Builds up a definition for the indicated wrapped type. - */ -void InterrogateBuilder:: -define_wrapped_type(InterrogateType &itype, CPPPointerType *cpptype) { - itype._flags |= (InterrogateType::F_wrapped | InterrogateType::F_pointer); - itype._wrapped_type = get_type(cpptype->_pointing_at, false); -} - -/** - * Builds up a definition for the indicated wrapped type. - */ -void InterrogateBuilder:: -define_wrapped_type(InterrogateType &itype, CPPConstType *cpptype) { - itype._flags |= (InterrogateType::F_wrapped | InterrogateType::F_const); - itype._wrapped_type = get_type(cpptype->_wrapped_around, false); -} - -/** - * Builds up a definition for the indicated struct type. - */ -void InterrogateBuilder:: -define_struct_type(InterrogateType &itype, CPPStructType *cpptype, - TypeIndex type_index, bool forced) { - if (cpptype->get_simple_name().empty()) { - // If the type has no name, forget it. We don't export anonymous structs. - return; - } - - cpptype = TypeManager::resolve_type(cpptype)->as_struct_type(); - assert(cpptype != nullptr); - bool has_virt_methods = cpptype->is_polymorphic(); - - switch (cpptype->_type) { - case CPPExtensionType::T_class: - itype._flags |= InterrogateType::F_class; - break; - - case CPPExtensionType::T_struct: - itype._flags |= InterrogateType::F_struct; - break; - - case CPPExtensionType::T_union: - itype._flags |= InterrogateType::F_union; - break; - - default: - break; - } - - if (cpptype->is_final()) { - itype._flags |= InterrogateType::F_final; - } - - if (cpptype->_file.is_c_file()) { - // This type declaration appears in a .C file. We can only export types - // defined in a .h file. - return; - } - - if (!forced && - (cpptype->_file._source != CPPFile::S_local || - in_ignorefile(cpptype->_file._filename_as_referenced))) { - // The struct type is defined in some other package or in an ignorable - // file, so don't try to output it. - - // This means we also don't gather any information about its derivations - // or determine if an implicit destructor is necessary. However, this is - // not important, and it causes problems if we do (how many implicit - // destructors do we need, anyway?). - itype._flags &= ~InterrogateType::F_fully_defined; - return; - } - - // Make sure the class declaration within its parent scope isn't private or - // protected. If it is, we can't export any of its members. - if (TypeManager::involves_unpublished(cpptype)) { - itype._flags &= ~InterrogateType::F_fully_defined; - itype._flags |= InterrogateType::F_unpublished; - return; - } - if (TypeManager::involves_protected(cpptype)) { - itype._flags &= ~InterrogateType::F_fully_defined; - return; - } - - // A struct type should always be global. - itype._flags |= InterrogateType::F_global; - - CPPScope *scope = cpptype->_scope; - - CPPStructType::Derivation::const_iterator bi; - for (bi = cpptype->_derivation.begin(); - bi != cpptype->_derivation.end(); - ++bi) { - - const CPPStructType::Base &base = (*bi); - if (base._vis <= V_public) { - CPPType *base_type = TypeManager::resolve_type(base._base, scope); - TypeIndex base_index = get_type(base_type, false); - - if (base_index == 0) { - if (base_type != nullptr) { - nout << *cpptype << " reports a derivation from invalid type " << *base_type << ".\n"; - } else { - nout << *cpptype << " reports a derivation from an invalid type.\n"; - } - - } else { - InterrogateType::Derivation d; - d._flags = 0; - d._base = base_index; - d._upcast = 0; - d._downcast = 0; - - // Do we need to synthesize upcast and downcast functions? - bool generate_casts = false; - - // Function To Generate all castsss Posible.. - if (base._is_virtual) { - // We do in the presence of virtual inheritance. - generate_casts = true; - - } else if (bi != cpptype->_derivation.begin()) { - // Or if we're not talking about the leftmost fork of multiple - // inheritance. - generate_casts = true; - - } else if (cpptype->_derivation.size() != 1 && - left_inheritance_requires_upcast) { - // Or even if we are the leftmost fork of multiple inheritance, if - // the flag is set indicating that this requires a pointer change. - // (For many compilers, this does not require a pointer change.) - generate_casts = true; - - } else if (has_virt_methods && (base_type->as_struct_type() == nullptr || !base_type->as_struct_type()->is_polymorphic())) { - // Finally, if this class has virtual methods, but its parent - // doesn't, then we have to upcast (because this class will require - // space for a virtual function table pointer, while the parent - // class won't). - generate_casts = true; - } - - if (generate_casts) { - d._upcast = get_cast_function(base_type, cpptype, "upcast"); - d._flags |= InterrogateType::DF_upcast; - - if (base._is_virtual) { - // If this is a virtual inheritance, we can't write a downcast. - d._flags |= InterrogateType::DF_downcast_impossible; - } else { - d._downcast = get_cast_function(cpptype, base_type, "downcast"); - d._flags |= InterrogateType::DF_downcast; - } - } - - itype._derivations.push_back(d); - } - } - } - - CPPScope::Declarations::const_iterator di; - for (di = scope->_declarations.begin(); - di != scope->_declarations.end(); - ++di) { - - if ((*di)->get_subtype() == CPPDeclaration::ST_instance) { - CPPInstance *inst = (*di)->as_instance(); - if (inst->_type->get_subtype() == CPPDeclaration::ST_function) { - // Here's a method declaration. - define_method(inst, itype, cpptype, scope); - - } else { - // Here's a data member declaration. - ElementIndex data_member = scan_element(inst, cpptype, scope); - if (data_member != 0) { - itype._elements.push_back(data_member); - } - } - - } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) { - CPPType *type = (*di)->as_type_declaration()->_type; - - if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) { - if (type->as_struct_type() != nullptr || - type->as_enum_type() != nullptr) { - // Here's a nested class or enum definition. - type->_vis = (*di)->_vis; - - CPPExtensionType *nested_type = type->as_extension_type(); - assert(nested_type != nullptr); - - // For now, we don't allow anonymous structs. - if (nested_type->_ident != nullptr || - nested_type->as_enum_type() != nullptr) { - TypeIndex nested_index = get_type(nested_type, false); - itype._nested_types.push_back(nested_index); - } - } - } - } else if ((*di)->get_subtype() == CPPDeclaration::ST_enum) { - CPPType *type = (*di)->as_enum_type(); - - // An anonymous enum type. - if (type->_vis <= min_vis) { - TypeIndex nested_index = get_type(type, false); - itype._nested_types.push_back(nested_index); - } - - } else if ((*di)->get_subtype() == CPPDeclaration::ST_typedef) { - CPPTypedefType *type = (*di)->as_typedef_type(); - - // A nested typedef. Unwrap it to find out what it's pointing to. - CPPType *wrapped_type = type->_type; - - while (wrapped_type->get_subtype() == CPPDeclaration::ST_typedef) { - wrapped_type = wrapped_type->as_typedef_type()->_type; - } - - CPPStructType *struct_type = wrapped_type->as_struct_type(); - if (struct_type != nullptr) { - // We only export typedefs to structs, for now. - - if (type->_vis <= min_vis) { - TypeIndex nested_index = get_type(type, false); - itype._nested_types.push_back(nested_index); - } - } - - } else if ((*di)->get_subtype() == CPPDeclaration::ST_make_property) { - ElementIndex element_index = get_make_property((*di)->as_make_property(), cpptype, scope); - if (find(itype._elements.begin(), itype._elements.end(), element_index) == itype._elements.end()) { - itype._elements.push_back(element_index); - } - - } else if ((*di)->get_subtype() == CPPDeclaration::ST_make_seq) { - MakeSeqIndex make_seq_index = get_make_seq((*di)->as_make_seq(), cpptype); - itype._make_seqs.push_back(make_seq_index); - } - } - - // See if we need to generate an implicit default constructor. - CPPFunctionGroup *constructor = cpptype->get_constructor(); - if (constructor == nullptr && cpptype->is_default_constructible()) { - // Make a default constructor. - CPPType *void_type = TypeManager::get_void_type(); - CPPParameterList *params = new CPPParameterList; - CPPFunctionType *ftype = new CPPFunctionType(void_type, params, CPPFunctionType::F_constructor); - - // Now make up an instance for the default constructor. - CPPInstance *function = new CPPInstance(ftype, cpptype->get_simple_name()); - function->_storage_class |= CPPInstance::SC_inline | CPPInstance::SC_defaulted; - function->_vis = V_published; - - FunctionIndex index = get_function(function, "", cpptype, cpptype->get_scope(), - InterrogateFunction::F_constructor); - if (find(itype._constructors.begin(), itype._constructors.end(), - index) == itype._constructors.end()) { - itype._constructors.push_back(index); - } - } - - // See if we need to generate an implicit copy constructor. - CPPInstance *copy_constructor = cpptype->get_copy_constructor(); - if (copy_constructor == nullptr && - cpptype->is_copy_constructible()) { - // Make an implicit copy constructor. - CPPType *const_ref_type = TypeManager::wrap_const_reference(cpptype); - CPPInstance *param = new CPPInstance(const_ref_type, nullptr); - - CPPType *void_type = TypeManager::get_void_type(); - CPPParameterList *params = new CPPParameterList; - params->_parameters.push_back(param); - const int flags = CPPFunctionType::F_constructor | CPPFunctionType::F_copy_constructor; - CPPFunctionType *ftype = new CPPFunctionType(void_type, params, flags); - - // Now make up an instance for the copy constructor. - CPPInstance *function = new CPPInstance(ftype, cpptype->get_simple_name()); - function->_storage_class |= CPPInstance::SC_inline | CPPInstance::SC_defaulted; - function->_vis = V_published; - - FunctionIndex index = get_function(function, "", cpptype, cpptype->get_scope(), - InterrogateFunction::F_constructor); - if (find(itype._constructors.begin(), itype._constructors.end(), - index) == itype._constructors.end()) { - itype._constructors.push_back(index); - } - } - - if (!cpptype->is_destructible()) { - // There's no way to destruct the type. - itype._destructor = 0; - - } else if ((itype._flags & InterrogateType::F_inherited_destructor) != 0) { - // If we have inherited our virtual destructor from our base class, go - // ahead and assign the same function index. - assert(!itype._derivations.empty()); - TypeIndex base_type_index = itype._derivations.front()._base; - InterrogateType &base_type = InterrogateDatabase::get_ptr()-> - update_type(base_type_index); - - itype._destructor = base_type._destructor; - - } else if ((itype._flags & - (InterrogateType::F_true_destructor | - InterrogateType::F_private_destructor | - InterrogateType::F_inherited_destructor | - InterrogateType::F_implicit_destructor)) == 0) { - // If we didn't get a destructor at all, we should make a wrapper for one - // anyway. - string function_name = "~" + cpptype->get_simple_name(); - - // Make up a CPPFunctionType. - CPPType *void_type = TypeManager::get_void_type(); - CPPParameterList *params = new CPPParameterList; - CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0); - ftype->_flags |= CPPFunctionType::F_destructor; - - // Now make up an instance for the destructor. - CPPInstance *function = new CPPInstance(ftype, function_name); - - itype._destructor = get_function(function, "", - cpptype, cpptype->get_scope(), - InterrogateFunction::F_destructor); - itype._flags |= InterrogateType::F_implicit_destructor; - } -} - -/** - * Updates the function definition in the database to include whatever comment - * is associated with this declaration. This is called when we encounted a - * method definition outside of the class or function definition in a C++ - * file; the only new information this might include for us is the comment. - */ -void InterrogateBuilder:: -update_function_comment(CPPInstance *function, CPPScope *scope) { - if (function->_leading_comment == nullptr) { - // No comment anyway. Forget it. - return; - } - - // Get a function name so we can look this method up. - if (function->_ident->_native_scope != scope) { - function = new CPPInstance(*function); - function->_ident = new CPPIdentifier(*function->_ident); - function->_ident->_native_scope = scope; - } - CPPFunctionType *ftype = - function->_type->resolve_type(scope, &parser)->as_function_type(); - function->_type = ftype; - - string function_name = TypeManager::get_function_name(function); - string function_signature = TypeManager::get_function_signature(function); - - if (ftype->_flags & CPPFunctionType::F_unary_op) { - // This is a unary operator function. Name it differently so we don't - // consider it an overloaded version of a similarly-named binary operator. - function_name += "unary"; - } - - // Now look it up. - FunctionsByName::const_iterator tni = - _functions_by_name.find(function_name); - if (tni != _functions_by_name.end()) { - FunctionIndex index = (*tni).second; - - // Here it is! - InterrogateFunction &ifunction = - InterrogateDatabase::get_ptr()->update_function(index); - - // Update the comment. - string comment = trim_blanks(function->_leading_comment->_comment); - if (!ifunction._comment.empty()) { - ifunction._comment += "\n\n"; - } - ifunction._comment += comment; - - // Also update the particular wrapper comment. - InterrogateFunction::Instances::iterator ii = - ifunction._instances->find(function_signature); - if (ii != ifunction._instances->end()) { - if ((*ii).second->_leading_comment == nullptr || - function->_leading_comment->_comment.length() > - (*ii).second->_leading_comment->_comment.length()) { - (*ii).second->_leading_comment = function->_leading_comment; - } - } - } -} - - -/** - * Adds the indicated member function to the struct type, - */ -void InterrogateBuilder:: -define_method(CPPFunctionGroup *fgroup, InterrogateType &itype, - CPPStructType *struct_type, CPPScope *scope) { - CPPFunctionGroup::Instances::const_iterator fi; - for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) { - CPPInstance *function = (*fi); - define_method(function, itype, struct_type, scope); - } -} - -/** - * Adds the indicated member function to the struct type, - */ -void InterrogateBuilder:: -define_method(CPPInstance *function, InterrogateType &itype, - CPPStructType *struct_type, CPPScope *scope) { - assert(function != nullptr); - assert(function->_type != nullptr && - function->_type->as_function_type() != nullptr); - CPPFunctionType *ftype = - function->_type->resolve_type(scope, &parser)->as_function_type(); - - if (function->is_template()) { - // The function is a template function, not a true function. - return; - } - - if (function->_storage_class & CPPInstance::SC_deleted) { - // It was explicitly marked as deleted. - return; - } - - // As a special kludgey extension, we consider a public static method called - // "get_class_type()" to be marked published, even if it is not. This - // allows us to export all of the TypeHandle system stuff without having to - // specifically flag get_class_type() as published. - bool force_publish = false; - if (function->get_simple_name() == "get_class_type" && - (function->_storage_class & CPPInstance::SC_static) != 0 && - function->_vis <= V_public) { - force_publish = true; - } - - if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - // A destructor is a special case. If it's public, we export it (even if - // it's not published), but if it's protected or private, we don't export - // it, and we flag it so we don't try to synthesize one later. - if (function->_vis > V_public) { - itype._flags |= InterrogateType::F_private_destructor; - return; - } - force_publish = true; - } - - if (!force_publish && function->_vis > min_vis) { - // The function is not marked to be exported. - return; - } - - if (TypeManager::involves_protected(ftype)) { - // We can't export the function because it involves parameter types that - // are protected or private. - return; - } - - if (in_ignoreinvolved(ftype)) { - // The function or its parameters involves something that the user - // requested we ignore. - if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - itype._flags |= InterrogateType::F_private_destructor; - } - return; - } - - if (in_ignoremember(function->get_simple_name())) { - // The user requested us to ignore members of this name. - if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - itype._flags |= InterrogateType::F_private_destructor; - } - return; - } - - if ((function->_storage_class & CPPInstance::SC_inherited_virtual) != 0 && - struct_type->_derivation.size() == 1 && - struct_type->_derivation[0]._vis <= V_public && - !struct_type->_derivation[0]._is_virtual) { - // If this function is a virtual function whose first appearance is in - // some base class, we don't need to repeat its definition here, since - // we're already inheriting it properly. However, we may need to make an - // exception in the presence of multiple inheritance. - if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - itype._flags |= InterrogateType::F_inherited_destructor; - return; - } - - // Let's make sure the that first appearance of the function is actually - // declared published. - if (is_inherited_published(function, struct_type)) { - return; - } - // If it isn't, we should publish this method anyway. - } - - if (TypeManager::involves_rvalue_reference(ftype)) { - return; - } - - FunctionIndex index = get_function(function, "", struct_type, scope, 0); - if (index != 0) { - if ((ftype->_flags & CPPFunctionType::F_constructor) != 0) { - if (find(itype._constructors.begin(), itype._constructors.end(), - index) == itype._constructors.end()) { - itype._constructors.push_back(index); - } - - } else if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - itype._flags |= InterrogateType::F_true_destructor; - itype._destructor = index; - - } else if ((ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) { - if (find(itype._casts.begin(), itype._casts.end(), - index) == itype._casts.end()) { - itype._casts.push_back(index); - } - - } else { - if (find(itype._methods.begin(), itype._methods.end(), - index) == itype._methods.end()) { - itype._methods.push_back(index); - } - - // For an operator [] returning a non-const reference, we synthesize an - // "item-assignment" operator, which does not exist in C++ but does in - // scripting languages. This allows `obj[n] = ...` - if (ftype->_return_type != nullptr && - ftype->_return_type->is_reference() && - !ftype->_return_type->remove_reference()->is_const() && - (ftype->_flags & CPPFunctionType::F_const_method) == 0 && - function->get_simple_name() == "operator []") { - - // Make up a CPPFunctionType with extra parameter. - CPPType *assign_type = TypeManager::wrap_const_reference(ftype->_return_type->remove_reference()); - CPPParameterList *params = new CPPParameterList(*(ftype->_parameters)); - CPPInstance *param1 = new CPPInstance(assign_type, "assign_val"); - params->_parameters.push_back(param1); - CPPType *void_type = TypeManager::get_void_type(); - CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0); - - // Now make up an instance for the function. - CPPInstance *function = new CPPInstance(ftype, "operator []="); - function->_ident->_native_scope = scope; - - FunctionIndex index = get_function(function, "", - struct_type, scope, - InterrogateFunction::F_item_assignment); - if (index != 0) { - if (find(itype._methods.begin(), itype._methods.end(), - index) == itype._methods.end()) { - itype._methods.push_back(index); - } - } - } - } - } -} - -/** - * Builds up a definition for the indicated enum type. - */ -void InterrogateBuilder:: -define_enum_type(InterrogateType &itype, CPPEnumType *cpptype) { - itype._flags |= InterrogateType::F_enum; - - CPPScope *scope = cpptype->_parent_scope; - if (cpptype->_ident != nullptr) { - scope = cpptype->_ident->get_scope(&parser, &parser); - } - - // Make sure the enum declaration within its parent scope isn't private or - // protected. If it is, we can't export any of its members. - if (TypeManager::involves_unpublished(cpptype)) { - itype._flags &= ~InterrogateType::F_fully_defined; - itype._flags |= InterrogateType::F_unpublished; - return; - } - - if (cpptype->is_scoped()) { - itype._flags |= InterrogateType::F_scoped_enum; - } - - int next_value = 0; - - CPPEnumType::Elements::const_iterator ei; - for (ei = cpptype->_elements.begin(); - ei != cpptype->_elements.end(); - ++ei) { - CPPInstance *element = (*ei); - - // Tell the enum element where its native scope is, so we can get a - // properly scoped name. - - if (element->_ident->_native_scope != scope) { - element = new CPPInstance(*element); - element->_ident = new CPPIdentifier(*element->_ident); - element->_ident->_native_scope = scope; - } - - InterrogateType::EnumValue evalue; - evalue._name = element->get_simple_name(); - evalue._scoped_name = descope(element->get_local_name(&parser)); - - if (element->_leading_comment != nullptr) { - evalue._comment = trim_blanks(element->_leading_comment->_comment); - } - - if (element->_initializer != nullptr) { - CPPExpression::Result result = element->_initializer->evaluate(); - - if (result._type == CPPExpression::RT_error) { - nout << "enum value "; - element->output(nout, 0, &parser, true); - nout << " has invalid definition!\n"; - return; - } else { - next_value = result.as_integer(); - } - } - evalue._value = next_value; - itype._enum_values.push_back(evalue); - - next_value++; - } -} - -/** - * Builds up a definition for the indicated typedef. - */ -void InterrogateBuilder:: -define_typedef_type(InterrogateType &itype, CPPTypedefType *cpptype) { - itype._flags |= InterrogateType::F_typedef; - itype._wrapped_type = get_type(cpptype->_type, false); -} - -/** - * Builds up a definition for the indicated wrapped type. - */ -void InterrogateBuilder:: -define_array_type(InterrogateType &itype, CPPArrayType *cpptype) { - itype._flags |= InterrogateType::F_array; - itype._wrapped_type = get_type(cpptype->_element_type, false); - - if (cpptype->_bounds == nullptr) { - // This indicates an unsized array. - itype._array_size = -1; - } else { - itype._array_size = cpptype->_bounds->evaluate().as_integer(); - } -} - -/** - * Builds up a definition for the indicated extension type. - */ -void InterrogateBuilder:: -define_extension_type(InterrogateType &itype, CPPExtensionType *cpptype) { - // An "extension type" as returned by CPPParser is really a forward - // reference to an undefined struct or class type. - itype._flags &= ~InterrogateType::F_fully_defined; - - // But we can at least indicate which of the various extension types it is. - switch (cpptype->_type) { - case CPPExtensionType::T_enum: - case CPPExtensionType::T_enum_class: - case CPPExtensionType::T_enum_struct: - itype._flags |= InterrogateType::F_enum; - break; - - case CPPExtensionType::T_class: - itype._flags |= InterrogateType::F_class; - break; - - case CPPExtensionType::T_struct: - itype._flags |= InterrogateType::F_struct; - break; - - case CPPExtensionType::T_union: - itype._flags |= InterrogateType::F_union; - break; - } -} - -/** - * - */ -string InterrogateBuilder:: -trim_blanks(const string &str) { - size_t start = 0; - while (start < str.length() && isspace(str[start])) { - start++; - } - - size_t end = str.length(); - while (end > start && isspace(str[end - 1])) { - end--; - } - - return str.substr(start, end - start); -} diff --git a/dtool/src/interrogate/interrogateBuilder.h b/dtool/src/interrogate/interrogateBuilder.h deleted file mode 100644 index 1b182d3f56..0000000000 --- a/dtool/src/interrogate/interrogateBuilder.h +++ /dev/null @@ -1,167 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogateBuilder.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef INTERROGATEBUILDER_H -#define INTERROGATEBUILDER_H - -#include "dtoolbase.h" - -#include "interrogate_interface.h" -#include "interrogate_request.h" - -#include -#include -#include - -class CPPFunctionGroup; -class CPPInstance; -class CPPType; -class CPPSimpleType; -class CPPPointerType; -class CPPConstType; -class CPPExtensionType; -class CPPStructType; -class CPPEnumType; -class CPPTypedefType; -class CPPArrayType; -class CPPFunctionType; -class CPPScope; -class CPPIdentifier; -class CPPNameComponent; -class CPPManifest; -class CPPMakeProperty; -class CPPMakeSeq; -class InterrogateType; -class InterrogateFunction; -class FunctionRemap; -class InterfaceMaker; - -/** - * This class builds up the InterrogateDatabase based on the data indicated by - * CPPParser after reading the source code. - */ -class InterrogateBuilder { -public: - void add_source_file(const std::string &filename); - void read_command_file(std::istream &in); - void do_command(const std::string &command, const std::string ¶ms); - void build(); - void write_code(std::ostream &out_code, std::ostream *out_include, InterrogateModuleDef *def); - InterrogateModuleDef *make_module_def(int file_identifier); - - static std::string clean_identifier(const std::string &name); - static std::string descope(const std::string &name); - FunctionIndex get_destructor_for(CPPType *type); - - std::string get_preferred_name(CPPType *type); - static std::string hash_string(const std::string &name, int shift_offset); - TypeIndex get_type(CPPType *type, bool global); - -public: - typedef std::set Commands; - typedef std::map CommandParams; - void insert_param_list(InterrogateBuilder::Commands &commands, - const std::string ¶ms); - - bool in_forcetype(const std::string &name) const; - std::string in_renametype(const std::string &name) const; - bool in_ignoretype(const std::string &name) const; - std::string in_defconstruct(const std::string &name) const; - bool in_ignoreinvolved(const std::string &name) const; - bool in_ignoreinvolved(CPPType *type) const; - bool in_ignorefile(const std::string &name) const; - bool in_ignoremember(const std::string &name) const; - bool in_noinclude(const std::string &name) const; - bool should_include(const std::string &filename) const; - - bool is_inherited_published(CPPInstance *function, CPPStructType *struct_type); - - void remap_indices(std::vector &remaps); - void scan_function(CPPFunctionGroup *fgroup); - void scan_function(CPPInstance *function); - void scan_struct_type(CPPStructType *type); - void scan_enum_type(CPPEnumType *type); - void scan_typedef_type(CPPTypedefType *type); - void scan_manifest(CPPManifest *manifest); - ElementIndex scan_element(CPPInstance *element, CPPStructType *struct_type, - CPPScope *scope); - - FunctionIndex get_getter(CPPType *expr_type, std::string expression, - CPPStructType *struct_type, CPPScope *scope, - CPPInstance *element); - FunctionIndex get_setter(CPPType *expr_type, std::string expression, - CPPStructType *struct_type, CPPScope *scope, - CPPInstance *element); - FunctionIndex get_cast_function(CPPType *to_type, CPPType *from_type, - const std::string &prefix); - FunctionIndex - get_function(CPPInstance *function, std::string description, - CPPStructType *struct_type, CPPScope *scope, - int flags, const std::string &expression = std::string()); - - ElementIndex - get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CPPScope *scope); - - MakeSeqIndex - get_make_seq(CPPMakeSeq *make_seq, CPPStructType *struct_type); - - TypeIndex get_atomic_string_type(); - - void define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype); - void define_wrapped_type(InterrogateType &itype, CPPPointerType *cpptype); - void define_wrapped_type(InterrogateType &itype, CPPConstType *cpptype); - void define_struct_type(InterrogateType &itype, CPPStructType *cpptype, - TypeIndex type_index, bool forced); - void update_function_comment(CPPInstance *function, CPPScope *scope); - void define_method(CPPFunctionGroup *fgroup, InterrogateType &itype, - CPPStructType *struct_type, CPPScope *scope); - void define_method(CPPInstance *function, InterrogateType &itype, - CPPStructType *struct_type, CPPScope *scope); - void define_enum_type(InterrogateType &itype, CPPEnumType *cpptype); - void define_typedef_type(InterrogateType &itype, CPPTypedefType *cpptype); - void define_array_type(InterrogateType &itype, CPPArrayType *cpptype); - void define_extension_type(InterrogateType &itype, - CPPExtensionType *cpptype); - - static std::string trim_blanks(const std::string &str); - - typedef std::map TypesByName; - typedef std::map FunctionsByName; - typedef std::map MakeSeqsByName; - typedef std::map PropertiesByName; - - TypesByName _types_by_name; - FunctionsByName _functions_by_name; - MakeSeqsByName _make_seqs_by_name; - PropertiesByName _properties_by_name; - - typedef std::map IncludeFiles; - IncludeFiles _include_files; - - Commands _forcetype; - CommandParams _renametype; - Commands _ignoretype; - CommandParams _defconstruct; - Commands _ignoreinvolved; - Commands _ignorefile; - Commands _ignoremember; - Commands _noinclude; - - std::string _library_hash_name; - - friend class FunctionRemap; -}; - -extern InterrogateBuilder builder; - -#endif diff --git a/dtool/src/interrogate/interrogate_composite1.cxx b/dtool/src/interrogate/interrogate_composite1.cxx deleted file mode 100644 index 39f08c9fe4..0000000000 --- a/dtool/src/interrogate/interrogate_composite1.cxx +++ /dev/null @@ -1,14 +0,0 @@ - -#include "interrogateBuilder.cxx" -#include "functionRemap.cxx" -#include "functionWriter.cxx" -#include "functionWriterPtrFromPython.cxx" -#include "functionWriterPtrToPython.cxx" -#include "functionWriters.cxx" -#include "interfaceMaker.cxx" -#include "interfaceMakerC.cxx" -#include "interfaceMakerPython.cxx" -#include "interfaceMakerPythonNative.cxx" -#include "interfaceMakerPythonObj.cxx" -#include "interfaceMakerPythonSimple.cxx" - diff --git a/dtool/src/interrogate/interrogate_composite2.cxx b/dtool/src/interrogate/interrogate_composite2.cxx deleted file mode 100644 index a427cf2674..0000000000 --- a/dtool/src/interrogate/interrogate_composite2.cxx +++ /dev/null @@ -1,19 +0,0 @@ - -#include "interrogate.cxx" -#include "typeManager.cxx" -#include "parameterRemap.cxx" -#include "parameterRemapBasicStringPtrToString.cxx" -#include "parameterRemapBasicStringRefToString.cxx" -#include "parameterRemapBasicStringToString.cxx" -#include "parameterRemapCharStarToString.cxx" -#include "parameterRemapConcreteToPointer.cxx" -#include "parameterRemapConstToNonConst.cxx" -#include "parameterRemapEnumToInt.cxx" -#include "parameterRemapPTToPointer.cxx" -#include "parameterRemapReferenceToConcrete.cxx" -#include "parameterRemapReferenceToPointer.cxx" -#include "parameterRemapThis.cxx" -#include "parameterRemapToString.cxx" -#include "parameterRemapHandleToInt.cxx" -#include "parameterRemapUnchanged.cxx" - diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx deleted file mode 100644 index 5b42d1db02..0000000000 --- a/dtool/src/interrogate/interrogate_module.cxx +++ /dev/null @@ -1,621 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file interrogate_module.cxx - * @author drose - * @date 2000-08-08 - */ - -// This program generates a module-level file for interrogate. This is a -// higher level than library, and groups several libraries together. -// Presently, the only thing that goes into the module file is a python table, -// but who knows what the future holds. - -#include "interrogate_interface.h" -#include "interrogate_request.h" -#include "load_dso.h" -#include "pnotify.h" -#include "panda_getopt_long.h" -#include "preprocess_argv.h" -#include "vector_string.h" - -#include - -using std::cerr; -using std::string; - -// This contains a big source string determined at compile time. -extern const char interrogate_preamble_python_native[]; - -Filename output_code_filename; -string module_name; -string library_name; -bool build_c_wrappers = false; -bool build_python_wrappers = false; -bool build_python_native_wrappers = false; -bool track_interpreter = false; -vector_string imports; - -// Short command-line options. -static const char *short_options = ""; - -// Long command-line options. -enum CommandOptions { - CO_oc = 256, - CO_module, - CO_library, - CO_c, - CO_python, - CO_python_native, - CO_track_interpreter, - CO_import, -}; - -static struct option long_options[] = { - { "oc", required_argument, nullptr, CO_oc }, - { "module", required_argument, nullptr, CO_module }, - { "library", required_argument, nullptr, CO_library }, - { "c", no_argument, nullptr, CO_c }, - { "python", no_argument, nullptr, CO_python }, - { "python-native", no_argument, nullptr, CO_python_native }, - { "track-interpreter", no_argument, nullptr, CO_track_interpreter }, - { "import", required_argument, nullptr, CO_import }, - { nullptr } -}; - -/* -static string -upcase_string(const string &str) { - string result; - for (string::const_iterator si = str.begin(); - si != str.end(); - ++si) { - result += toupper(*si); - } - return result; -} -*/ - -/** - * Finds a dependency cycle between the given dependency mapping, starting at - * the node that is already placed in the given cycle vector. - */ -static bool find_dependency_cycle(vector_string &cycle, std::map > &dependencies) { - assert(!cycle.empty()); - - const std::set &deps = dependencies[cycle.back()]; - for (auto it = deps.begin(); it != deps.end(); ++it) { - auto it2 = std::find(cycle.begin(), cycle.end(), *it); - if (it2 != cycle.end()) { - // Chop off the part of the chain that is not relevant. - cycle.erase(cycle.begin(), it2); - cycle.push_back(*it); - return true; - } - - // Recurse. - cycle.push_back(*it); - if (find_dependency_cycle(cycle, dependencies)) { - return true; - } - cycle.pop_back(); - } - - return false; -} - -/** - * Given that a direct link has been established between the two libraries, - * finds the two types that make up this relationship and prints out the - * nature of their dependency. - */ -static bool print_dependent_types(const string &lib1, const string &lib2) { - for (int ti = 0; ti < interrogate_number_of_global_types(); ti++) { - TypeIndex thetype = interrogate_get_global_type(ti); - if (interrogate_type_has_module_name(thetype) && - interrogate_type_has_library_name(thetype) && - lib1 == interrogate_type_library_name(thetype) && - module_name == interrogate_type_module_name(thetype)) { - - // Get the dependencies for this library. - int num_derivations = interrogate_type_number_of_derivations(thetype); - for (int di = 0; di < num_derivations; ++di) { - TypeIndex basetype = interrogate_type_get_derivation(thetype, di); - if (interrogate_type_is_global(basetype) && - interrogate_type_has_library_name(basetype) && - interrogate_type_library_name(basetype) == lib2) { - cerr - << " " << interrogate_type_scoped_name(thetype) << " (" - << lib1 << ") inherits from " - << interrogate_type_scoped_name(basetype) << " (" << lib2 << ")\n"; - return true; - } - } - - // It also counts if this is a typedef pointing to another type. - if (interrogate_type_is_typedef(thetype)) { - TypeIndex wrapped = interrogate_type_wrapped_type(thetype); - if (interrogate_type_is_global(wrapped) && - interrogate_type_has_library_name(wrapped) && - interrogate_type_library_name(wrapped) == lib2) { - cerr - << " " << interrogate_type_scoped_name(thetype) << " (" - << lib1 << ") is a typedef to " - << interrogate_type_scoped_name(wrapped) << " (" << lib2 << ")\n"; - } - } - } - } - return false; -} - -int write_python_table_native(std::ostream &out) { - out << "\n#include \"dtoolbase.h\"\n" - << "#include \"interrogate_request.h\"\n\n" - << "#include \"py_panda.h\"\n\n"; - - int count = 0; - - std::map > dependencies; - -// out << "extern \"C\" {\n"; - - // Walk through all of the Python functions. - int num_functions = interrogate_number_of_functions(); - int fi; - for (fi = 0; fi < num_functions; fi++) { - FunctionIndex function_index = interrogate_get_function(fi); - - // Consider only those that belong in the module we asked for. if - // (interrogate_function_has_module_name(function_index) && module_name == - // interrogate_function_module_name(function_index)) { if it has a library - // name add it to set of libraries - if (interrogate_function_has_library_name(function_index)) { - string library_name = interrogate_function_library_name(function_index); - dependencies[library_name]; - } - // } - } - - for (int ti = 0; ti < interrogate_number_of_global_types(); ti++) { - TypeIndex thetype = interrogate_get_global_type(ti); - if (interrogate_type_has_module_name(thetype) && module_name == interrogate_type_module_name(thetype)) { - if (interrogate_type_has_library_name(thetype)) { - string library_name = interrogate_type_library_name(thetype); - std::set &deps = dependencies[library_name]; - - // Get the dependencies for this library. - int num_derivations = interrogate_type_number_of_derivations(thetype); - for (int di = 0; di < num_derivations; ++di) { - TypeIndex basetype = interrogate_type_get_derivation(thetype, di); - if (interrogate_type_is_global(basetype) && - interrogate_type_has_library_name(basetype)) { - string baselib = interrogate_type_library_name(basetype); - if (baselib != library_name) { - deps.insert(std::move(baselib)); - } - } - } - - if (interrogate_type_is_typedef(thetype)) { - TypeIndex wrapped = interrogate_type_wrapped_type(thetype); - if (interrogate_type_is_global(wrapped) && - interrogate_type_has_library_name(wrapped)) { - string wrappedlib = interrogate_type_library_name(wrapped); - if (wrappedlib != library_name) { - deps.insert(std::move(wrappedlib)); - } - } - } - } - } - } - - // Now add the libraries in their proper ordering, based on dependencies. - vector_string libraries; - while (libraries.size() < dependencies.size()) { - // We have this check to make sure we don't enter an infinite loop. - bool added_any = false; - - for (auto it = dependencies.begin(); it != dependencies.end(); ++it) { - const string &library_name = it->first; - std::set &deps = dependencies[library_name]; - - // Remove the dependencies that have already been added from the deps. - if (!deps.empty()) { - for (auto li = libraries.begin(); li != libraries.end(); ++li) { - deps.erase(*li); - } - } - - if (deps.empty()) { - // OK, no remaining dependencies, so we can add this. - if (std::find(libraries.begin(), libraries.end(), library_name) == libraries.end()) { - libraries.push_back(library_name); - added_any = true; - } - } - } - - if (!added_any) { - // Oh dear, we must have hit a circular dependency. Go through the - // remaining libraries to figure it out and print it. - cerr << "Circular dependency between libraries detected:\n"; - for (auto it = dependencies.begin(); it != dependencies.end(); ++it) { - const string &library_name = it->first; - std::set &deps = dependencies[library_name]; - if (deps.empty()) { - continue; - } - - // But since it does indicate a potential architectural flaw, we do - // want to let the user know about this. - vector_string cycle; - cycle.push_back(library_name); - if (!find_dependency_cycle(cycle, dependencies)) { - continue; - } - assert(cycle.size() >= 2); - - // Show the cycle of library dependencies. - auto ci = cycle.begin(); - cerr << " " << *ci; - for (++ci; ci != cycle.end(); ++ci) { - cerr << " -> " << *ci; - } - cerr << "\n"; - - // Now print out the actual types that make up the cycle. - ci = cycle.begin(); - string prev = *ci; - for (++ci; ci != cycle.end(); ++ci) { - print_dependent_types(prev, *ci); - prev = *ci; - } - - // We have to arbitrarily break one of the dependencies in order to be - // able to proceed. Break the first dependency. - dependencies[cycle[0]].erase(cycle[1]); - } - } - } - - vector_string::const_iterator ii; - for (ii = libraries.begin(); ii != libraries.end(); ++ii) { - printf("Referencing Library %s\n", (*ii).c_str()); - out << "extern const struct LibraryDef " << *ii << "_moddef;\n"; - out << "extern void Dtool_" << *ii << "_RegisterTypes();\n"; - out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n"; - } - - out.put('\n'); - - out << "#if PY_MAJOR_VERSION >= 3\n" - << "extern \"C\" EXPORT_CLASS PyObject *PyInit_" << library_name << "();\n" - << "#else\n" - << "extern \"C\" EXPORT_CLASS void init" << library_name << "();\n" - << "#endif\n"; - - out << "\n" - << "#if PY_MAJOR_VERSION >= 3\n" - << "static struct PyModuleDef py_" << library_name << "_module = {\n" - << " PyModuleDef_HEAD_INIT,\n" - << " \"" << module_name << "\",\n" - << " nullptr,\n" - << " -1,\n" - << " nullptr,\n" - << " nullptr, nullptr, nullptr, nullptr\n" - << "};\n" - << "\n" - << "PyObject *PyInit_" << library_name << "() {\n"; - - if (track_interpreter) { - out << " in_interpreter = 1;\n"; - } - - vector_string::const_iterator si; - for (si = imports.begin(); si != imports.end(); ++si) { - out << " PyImport_Import(PyUnicode_FromString(\"" << *si << "\"));\n"; - } - - for (ii = libraries.begin(); ii != libraries.end(); ii++) { - out << " Dtool_" << *ii << "_RegisterTypes();\n"; - } - out << "\n"; - - out << " const LibraryDef *defs[] = {"; - for(ii = libraries.begin(); ii != libraries.end(); ii++) { - out << "&" << *ii << "_moddef, "; - } - - out << "nullptr};\n" - << "\n" - << " PyObject *module = Dtool_PyModuleInitHelper(defs, &py_" << library_name << "_module);\n" - << " if (module != nullptr) {\n"; - - for (ii = libraries.begin(); ii != libraries.end(); ii++) { - out << " Dtool_" << *ii << "_BuildInstants(module);\n"; - } - - out << " }\n" - << " return module;\n" - << "}\n" - << "\n" - - << "#else // Python 2 case\n" - << "\n" - << "void init" << library_name << "() {\n"; - - if (track_interpreter) { - out << " in_interpreter = 1;\n"; - } - - for (si = imports.begin(); si != imports.end(); ++si) { - out << " PyImport_Import(PyUnicode_FromString(\"" << *si << "\"));\n"; - } - - for (ii = libraries.begin(); ii != libraries.end(); ii++) { - out << " Dtool_" << *ii << "_RegisterTypes();\n"; - } - out << "\n"; - - out << " const LibraryDef *defs[] = {"; - for(ii = libraries.begin(); ii != libraries.end(); ii++) { - out << "&" << *ii << "_moddef, "; - } - - out << "nullptr};\n" - << "\n" - << " PyObject *module = Dtool_PyModuleInitHelper(defs, \"" << module_name << "\");\n" - << " if (module != nullptr) {\n"; - - for (ii = libraries.begin(); ii != libraries.end(); ii++) { - out << " Dtool_" << *ii << "_BuildInstants(module);\n"; - } - - out << " }\n" - << "}\n" - << "#endif\n" - << "\n"; - - - return count; -} - -int write_python_table(std::ostream &out) { - out << "\n#include \"dtoolbase.h\"\n" - << "#include \"interrogate_request.h\"\n\n" - << "#undef _POSIX_C_SOURCE\n" - << "#include \"Python.h\"\n\n"; - - int count = 0; - - // First, we have to declare extern C prototypes for each of the function - // names. - - out << "extern \"C\" {\n"; - - // Walk through all of the Python functions. - int num_functions = interrogate_number_of_functions(); - int fi; - for (fi = 0; fi < num_functions; fi++) { - FunctionIndex function_index = interrogate_get_function(fi); - - // Consider only those that belong in the module we asked for. - if (interrogate_function_has_module_name(function_index) && - module_name == interrogate_function_module_name(function_index)) { - - // For each function, get all of the python wrappers. - int num_wrappers = - interrogate_function_number_of_python_wrappers(function_index); - - for (int wi = 0; wi < num_wrappers; wi++) { - FunctionWrapperIndex wrapper_index = - interrogate_function_python_wrapper(function_index, wi); - - if (interrogate_wrapper_is_callable_by_name(wrapper_index)) { - count++; - const char *wrapper_name = - interrogate_wrapper_name(wrapper_index); - out << " PyObject *" << wrapper_name - << "(PyObject *self, PyObject *args);\n"; - } - } - } - } - - out << "}\n\n"; - - // Now go back through and build the table of function names. - out << "static PyMethodDef python_methods[" << count + 1 << "] = {\n"; - - // Walk through all of the Python functions. - for (fi = 0; fi < num_functions; fi++) { - FunctionIndex function_index = interrogate_get_function(fi); - - // Consider only those that belong in the module we asked for. - if (interrogate_function_has_module_name(function_index) && - module_name == interrogate_function_module_name(function_index)) { - - // For each function, get all of the python wrappers. - int num_wrappers = - interrogate_function_number_of_python_wrappers(function_index); - for (int wi = 0; wi < num_wrappers; wi++) { - FunctionWrapperIndex wrapper_index = - interrogate_function_python_wrapper(function_index, wi); - - if (interrogate_wrapper_is_callable_by_name(wrapper_index)) { - const char *wrapper_name = - interrogate_wrapper_name(wrapper_index); - out << " { \"" - << wrapper_name << "\", &" - << wrapper_name << ", METH_VARARGS },\n"; - } - } - } - } - - if (library_name.empty()) { - library_name = module_name; - } - - out << " { nullptr, nullptr }\n" - << "};\n\n" - - << "#if PY_MAJOR_VERSION >= 3\n" - << "static struct PyModuleDef python_module = {\n" - << " PyModuleDef_HEAD_INIT,\n" - << " \"" << library_name << "\",\n" - << " nullptr,\n" - << " -1,\n" - << " python_methods,\n" - << " nullptr, nullptr, nullptr, nullptr\n" - << "};\n\n" - - << "#define INIT_FUNC PyObject *PyInit_" << library_name << "\n" - << "#else\n" - << "#define INIT_FUNC void init" << library_name << "\n" - << "#endif\n\n" - - << "#ifdef _WIN32\n" - << "extern \"C\" __declspec(dllexport) INIT_FUNC();\n" - << "#else\n" - << "extern \"C\" INIT_FUNC();\n" - << "#endif\n\n" - - << "INIT_FUNC() {\n"; - - if (track_interpreter) { - out << " in_interpreter = 1;\n"; - } - - out << "#if PY_MAJOR_VERSION >= 3\n" - << " return PyModule_Create(&python_module);\n" - << "#else\n" - << " Py_InitModule(\"" << library_name << "\", python_methods);\n" - << "#endif\n" - << "}\n\n"; - - return count; -} - -int main(int argc, char *argv[]) { - extern char *optarg; - extern int optind; - int flag; - - preprocess_argv(argc, argv); - flag = getopt_long_only(argc, argv, short_options, long_options, nullptr); - while (flag != EOF) { - switch (flag) { - case CO_oc: - output_code_filename = optarg; - break; - - case CO_module: - module_name = optarg; - break; - - case CO_library: - library_name = optarg; - break; - - case CO_c: - build_c_wrappers = true; - break; - - case CO_python: - build_python_wrappers = true; - break; - - case CO_python_native: - build_python_native_wrappers = true; - break; - - case CO_track_interpreter: - track_interpreter = true; - break; - - case CO_import: - imports.push_back(optarg); - break; - - default: - exit(1); - } - flag = getopt_long_only(argc, argv, short_options, long_options, nullptr); - } - - argc -= (optind-1); - argv += (optind-1); - - if (argc < 2) { - nout - << "\nUsage:\n" - << " interrogate-module [opts] libname.in [libname.in ...]\n\n"; - exit(1); - } - - output_code_filename.set_text(); - - if (!build_c_wrappers && !build_python_wrappers && !build_python_native_wrappers) { - build_c_wrappers = true; - } - - for (int i = 1; i < argc; i++) { - string param = argv[i]; - - - if (param.length() > 3 && param.substr(param.length() - 3) == ".in") { - // If the filename ends in ".in", it's an interrogate database file, not - // a shared library--read it directly. - interrogate_request_database(param.c_str()); - - } else { - // Otherwise, assume it's a shared library, and try to load it. - Filename pathname = argv[i]; - pathname.set_type(Filename::T_dso); - nout << "Loading " << pathname << "\n"; - void *dl = load_dso(DSearchPath(), pathname); - if (dl == nullptr) { - nout << "Unable to load: " << load_dso_error() << "\n"; - exit(1); - } - } - } - - // Now output the table. - if (!output_code_filename.empty()) { - pofstream output_code; - - if (!output_code_filename.open_write(output_code)) { - nout << "Unable to write to " << output_code_filename << "\n"; - } else { - - if (build_python_wrappers) { - int count = write_python_table(output_code); - nout << count << " python function wrappers exported.\n"; - } - - if (build_python_native_wrappers) { - write_python_table_native(output_code); - - // Output the support code. - output_code << interrogate_preamble_python_native << "\n"; - } - } - } - - if (interrogate_error_flag()) { - nout << "Error reading interrogate data.\n"; - output_code_filename.unlink(); - exit(1); - } - - return (0); -} diff --git a/dtool/src/interrogate/parameterRemap.I b/dtool/src/interrogate/parameterRemap.I deleted file mode 100644 index dac104e87f..0000000000 --- a/dtool/src/interrogate/parameterRemap.I +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemap.I - * @author drose - * @date 2000-08-01 - */ - -/** - * - */ -INLINE ParameterRemap:: -ParameterRemap(CPPType *orig_type) : - _orig_type(orig_type), - _new_type(orig_type) -{ - _is_valid = true; - _temporary_type = nullptr; - _default_value = nullptr; -} - -/** - * - */ -INLINE bool ParameterRemap:: -is_valid() const { - return _is_valid; -} - -/** - * Returns the type of the original, C++ parameter or return value. - */ -INLINE CPPType *ParameterRemap:: -get_orig_type() const { - return _orig_type; -} - -/** - * Returns the type of the wrapper's parameter or return value. This is the - * type that will be reported in the interrogate database, and the type that - * the scripting language is expected to deal with. - */ -INLINE CPPType *ParameterRemap:: -get_new_type() const { - return _new_type; -} - -/** - * Returns the type of any temporary variables used to hold the return value - * before returning it. This is normally the same as get_new_type(), but in - * some circumstances it may need to be different. - */ -INLINE CPPType *ParameterRemap:: -get_temporary_type() const { - if (_temporary_type == nullptr) { - return _new_type; - } else { - return _temporary_type; - } -} - -/** - * Returns true if this particular parameter has a default value defined. - */ -INLINE bool ParameterRemap:: -has_default_value() const { - return (_default_value != nullptr); -} - -/** - * Returns the expression corresponding to this parameter's default value. - */ -INLINE CPPExpression *ParameterRemap:: -get_default_value() const { - return _default_value; -} - -/** - * Records a default value to be associated with this parameter. - */ -INLINE void ParameterRemap:: -set_default_value(CPPExpression *expr) { - _default_value = expr; -} diff --git a/dtool/src/interrogate/parameterRemap.cxx b/dtool/src/interrogate/parameterRemap.cxx deleted file mode 100644 index 4794c7c16d..0000000000 --- a/dtool/src/interrogate/parameterRemap.cxx +++ /dev/null @@ -1,118 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemap.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "parameterRemap.h" - -using std::string; - - -/** - * - */ -ParameterRemap:: -~ParameterRemap() { -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemap:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << variable_name; -} - -/** - * This will be called immediately before get_return_expr(). It outputs - * whatever lines the remapper needs to the function to set up its return - * value, e.g. to declare a temporary variable or something. It should - * return the modified expression. - */ -string ParameterRemap:: -prepare_return_expr(std::ostream &, int, const string &expression) { - return expression; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemap:: -get_return_expr(const string &expression) { - return expression; -} - -/** - * Returns the string that converts the expression stored in the indicated - * temporary variable to the appropriate return value type. This is normally - * a pass-through, but in cases when the temporary variable type must be - * different than the return type (i.e. get_temporary_type() != - * get_new_type()), this might perform some operation. - */ -string ParameterRemap:: -temporary_to_return(const string &temporary) { - return temporary; -} - -/** - * Returns true if the return value represents a value that was newly - * allocated, and hence must be explicitly deallocated later by the caller. - */ -bool ParameterRemap:: -return_value_needs_management() { - return false; -} - -/** - * If return_value_needs_management() returns true, this should return the - * index of the function that should be called when it is time to destruct the - * return value. It will generally be the same as the destructor for the - * class we just returned a pointer to. - */ -FunctionIndex ParameterRemap:: -get_return_value_destructor() { - return 0; -} - -/** - * This is a hack around a problem VC++ has with overly-complex expressions, - * particularly in conjunction with the 'new' operator. If this parameter - * type is one that will probably give VC++ a headache, this should be set - * true to indicate that the code generator should save the return value - * expression into a temporary variable first, and pass the temporary variable - * name in instead. - */ -bool ParameterRemap:: -return_value_should_be_simple() { - return false; -} - - -/** - * Returns true if the type represented by the conversion is now the atomic - * string type. We have to have this crazy method for representing atomic - * string, because there's no such type in C (and hence no corresponding - * CPPType *). - */ -bool ParameterRemap:: -new_type_is_atomic_string() { - return false; -} - -/** - * Returns true if this is the "this" parameter. - */ -bool ParameterRemap:: -is_this() { - return false; -} diff --git a/dtool/src/interrogate/parameterRemap.h b/dtool/src/interrogate/parameterRemap.h deleted file mode 100644 index 9ae351e29c..0000000000 --- a/dtool/src/interrogate/parameterRemap.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemap.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef PARAMETERREMAP_H -#define PARAMETERREMAP_H - -#include "dtoolbase.h" - -#include "interrogate_interface.h" - -class CPPType; -class CPPExpression; - -/** - * An abstract base class for a number of different kinds of ways to remap - * parameters for passing to wrapper functions. - * - * Certain kinds of function parameters that are legal in C++ (for instance, - * passing by reference, or passing structures as concrete values) are not - * legal for a typical scripting language. We map these types of parameters - * to something equivalent (for instance, a reference becomes a pointer). - * - * For each kind of possible remapping, we define a class derived from - * ParameterRemap that defines the exact nature of the remap. - */ -class ParameterRemap { -public: - INLINE ParameterRemap(CPPType *orig_type); - virtual ~ParameterRemap(); - - INLINE bool is_valid() const; - - INLINE CPPType *get_orig_type() const; - INLINE CPPType *get_new_type() const; - INLINE CPPType *get_temporary_type() const; - INLINE bool has_default_value() const; - INLINE CPPExpression *get_default_value() const; - INLINE void set_default_value(CPPExpression *expr); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string prepare_return_expr(std::ostream &out, int indent_level, - const std::string &expression); - virtual std::string get_return_expr(const std::string &expression); - virtual std::string temporary_to_return(const std::string &temporary); - virtual bool return_value_needs_management(); - virtual FunctionIndex get_return_value_destructor(); - virtual bool return_value_should_be_simple(); - virtual bool new_type_is_atomic_string(); - virtual bool is_this(); - -protected: - bool _is_valid; - - CPPType *_orig_type; - CPPType *_new_type; - CPPType *_temporary_type; - CPPExpression *_default_value; -}; - -#include "parameterRemap.I" - -#endif diff --git a/dtool/src/interrogate/parameterRemapBasicStringPtrToString.cxx b/dtool/src/interrogate/parameterRemapBasicStringPtrToString.cxx deleted file mode 100644 index 07dad4694a..0000000000 --- a/dtool/src/interrogate/parameterRemapBasicStringPtrToString.cxx +++ /dev/null @@ -1,83 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapBasicStringPtrToString.cxx - * @author drose - * @date 2009-08-11 - */ - -#include "parameterRemapBasicStringPtrToString.h" -#include "interrogate.h" - -using std::string; - -/** - * - */ -ParameterRemapBasicStringPtrToString:: -ParameterRemapBasicStringPtrToString(CPPType *orig_type) : - ParameterRemapToString(orig_type) -{ - static CPPType *const_char_star_type = nullptr; - if (const_char_star_type == nullptr) { - const_char_star_type = parser.parse_type("const char *"); - } - - _new_type = const_char_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapBasicStringPtrToString:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << "&std::string(" << variable_name << ")"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapBasicStringPtrToString:: -get_return_expr(const string &expression) { - return "(" + expression + ")->c_str()"; -} - -/** - * - */ -ParameterRemapBasicWStringPtrToWString:: -ParameterRemapBasicWStringPtrToWString(CPPType *orig_type) : - ParameterRemapToWString(orig_type) -{ - static CPPType *const_wchar_star_type = nullptr; - if (const_wchar_star_type == nullptr) { - const_wchar_star_type = parser.parse_type("const wchar_t *"); - } - - _new_type = const_wchar_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapBasicWStringPtrToWString:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << "&std::wstring(" << variable_name << ")"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapBasicWStringPtrToWString:: -get_return_expr(const string &expression) { - return "(" + expression + ")->c_str()"; -} diff --git a/dtool/src/interrogate/parameterRemapBasicStringPtrToString.h b/dtool/src/interrogate/parameterRemapBasicStringPtrToString.h deleted file mode 100644 index c0c385af5e..0000000000 --- a/dtool/src/interrogate/parameterRemapBasicStringPtrToString.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapBasicStringPtrToString.h - * @author drose - * @date 2009-08-11 - */ - -#ifndef PARAMETERREMAPBASICSTRINGPTRTOSTRING_H -#define PARAMETERREMAPBASICSTRINGPTRTOSTRING_H - -#include "dtoolbase.h" - -#include "parameterRemapToString.h" - -/** - * Maps a const pointer to a basic_string to an atomic string. - */ -class ParameterRemapBasicStringPtrToString : public ParameterRemapToString { -public: - ParameterRemapBasicStringPtrToString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -/** - * Maps a const pointer to a basic_string to an atomic string. - */ -class ParameterRemapBasicWStringPtrToWString : public ParameterRemapToWString { -public: - ParameterRemapBasicWStringPtrToWString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapBasicStringRefToString.cxx b/dtool/src/interrogate/parameterRemapBasicStringRefToString.cxx deleted file mode 100644 index 90cd3d7e45..0000000000 --- a/dtool/src/interrogate/parameterRemapBasicStringRefToString.cxx +++ /dev/null @@ -1,83 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapBasicStringRefToString.cxx - * @author drose - * @date 2000-08-09 - */ - -#include "parameterRemapBasicStringRefToString.h" -#include "interrogate.h" - -using std::string; - -/** - * - */ -ParameterRemapBasicStringRefToString:: -ParameterRemapBasicStringRefToString(CPPType *orig_type) : - ParameterRemapToString(orig_type) -{ - static CPPType *const_char_star_type = nullptr; - if (const_char_star_type == nullptr) { - const_char_star_type = parser.parse_type("const char *"); - } - - _new_type = const_char_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapBasicStringRefToString:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << "std::string(" << variable_name << ")"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapBasicStringRefToString:: -get_return_expr(const string &expression) { - return "(" + expression + ").c_str()"; -} - -/** - * - */ -ParameterRemapBasicWStringRefToWString:: -ParameterRemapBasicWStringRefToWString(CPPType *orig_type) : - ParameterRemapToWString(orig_type) -{ - static CPPType *const_wchar_star_type = nullptr; - if (const_wchar_star_type == nullptr) { - const_wchar_star_type = parser.parse_type("const wchar_t *"); - } - - _new_type = const_wchar_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapBasicWStringRefToWString:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << "std::wstring(" << variable_name << ")"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapBasicWStringRefToWString:: -get_return_expr(const string &expression) { - return "(" + expression + ").c_str()"; -} diff --git a/dtool/src/interrogate/parameterRemapBasicStringRefToString.h b/dtool/src/interrogate/parameterRemapBasicStringRefToString.h deleted file mode 100644 index 546e5aad97..0000000000 --- a/dtool/src/interrogate/parameterRemapBasicStringRefToString.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapBasicStringRefToString.h - * @author drose - * @date 2000-08-09 - */ - -#ifndef PARAMETERREMAPBASICSTRINGREFTOSTRING_H -#define PARAMETERREMAPBASICSTRINGREFTOSTRING_H - -#include "dtoolbase.h" - -#include "parameterRemapToString.h" - -/** - * Maps a const reference to a basic_string to an atomic string. - */ -class ParameterRemapBasicStringRefToString : public ParameterRemapToString { -public: - ParameterRemapBasicStringRefToString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -/** - * Maps a const reference to a basic_string to an atomic string. - */ -class ParameterRemapBasicWStringRefToWString : public ParameterRemapToWString { -public: - ParameterRemapBasicWStringRefToWString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapBasicStringToString.cxx b/dtool/src/interrogate/parameterRemapBasicStringToString.cxx deleted file mode 100644 index 46ce08c9c7..0000000000 --- a/dtool/src/interrogate/parameterRemapBasicStringToString.cxx +++ /dev/null @@ -1,111 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapBasicStringToString.cxx - * @author drose - * @date 2000-08-09 - */ - -#include "parameterRemapBasicStringToString.h" -#include "interfaceMaker.h" -#include "interrogate.h" - -using std::ostream; -using std::string; - -/** - * - */ -ParameterRemapBasicStringToString:: -ParameterRemapBasicStringToString(CPPType *orig_type) : - ParameterRemapToString(orig_type) -{ - static CPPType *const_char_star_type = nullptr; - if (const_char_star_type == nullptr) { - const_char_star_type = parser.parse_type("const char *"); - } - - _new_type = const_char_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapBasicStringToString:: -pass_parameter(ostream &out, const string &variable_name) { - out << "std::string(" << variable_name << ")"; -} - -/** - * This will be called immediately before get_return_expr(). It outputs - * whatever lines the remapper needs to the function to set up its return - * value, e.g. to declare a temporary variable or something. It should - * return the modified expression. - */ -string ParameterRemapBasicStringToString:: -prepare_return_expr(ostream &out, int indent_level, const string &expression) { - InterfaceMaker::indent(out, indent_level) - << "static std::string string_holder = " << expression << ";\n"; - return "string_holder"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapBasicStringToString:: -get_return_expr(const string &expression) { - return "string_holder.c_str()"; -} - -/** - * - */ -ParameterRemapBasicWStringToWString:: -ParameterRemapBasicWStringToWString(CPPType *orig_type) : - ParameterRemapToWString(orig_type) -{ - static CPPType *const_wchar_star_type = nullptr; - if (const_wchar_star_type == nullptr) { - const_wchar_star_type = parser.parse_type("const wchar_t *"); - } - - _new_type = const_wchar_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapBasicWStringToWString:: -pass_parameter(ostream &out, const string &variable_name) { - out << "std::wstring(" << variable_name << ")"; -} - -/** - * This will be called immediately before get_return_expr(). It outputs - * whatever lines the remapper needs to the function to set up its return - * value, e.g. to declare a temporary variable or something. It should - * return the modified expression. - */ -string ParameterRemapBasicWStringToWString:: -prepare_return_expr(ostream &out, int indent_level, const string &expression) { - InterfaceMaker::indent(out, indent_level) - << "static std::wstring string_holder = " << expression << ";\n"; - return "string_holder"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapBasicWStringToWString:: -get_return_expr(const string &expression) { - return "string_holder.c_str()"; -} diff --git a/dtool/src/interrogate/parameterRemapBasicStringToString.h b/dtool/src/interrogate/parameterRemapBasicStringToString.h deleted file mode 100644 index d27da23796..0000000000 --- a/dtool/src/interrogate/parameterRemapBasicStringToString.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapBasicStringToString.h - * @author drose - * @date 2000-08-09 - */ - -#ifndef PARAMETERREMAPBASICSTRINGTOSTRING_H -#define PARAMETERREMAPBASICSTRINGTOSTRING_H - -#include "dtoolbase.h" - -#include "parameterRemapToString.h" - -/** - * Maps a concrete basic_string to an atomic string. - */ -class ParameterRemapBasicStringToString : public ParameterRemapToString { -public: - ParameterRemapBasicStringToString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string prepare_return_expr(std::ostream &out, int indent_level, - const std::string &expression); - virtual std::string get_return_expr(const std::string &expression); -}; - -/** - * Maps a concrete basic_string to an atomic string. - */ -class ParameterRemapBasicWStringToWString : public ParameterRemapToWString { -public: - ParameterRemapBasicWStringToWString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string prepare_return_expr(std::ostream &out, int indent_level, - const std::string &expression); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapCharStarToString.cxx b/dtool/src/interrogate/parameterRemapCharStarToString.cxx deleted file mode 100644 index e791fe9c61..0000000000 --- a/dtool/src/interrogate/parameterRemapCharStarToString.cxx +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapCharStarToString.cxx - * @author drose - * @date 2000-08-09 - */ - -#include "parameterRemapCharStarToString.h" - -/** - * - */ -ParameterRemapCharStarToString:: -ParameterRemapCharStarToString(CPPType *orig_type) : - ParameterRemapToString(orig_type) -{ -} - -/** - * - */ -ParameterRemapWCharStarToWString:: -ParameterRemapWCharStarToWString(CPPType *orig_type) : - ParameterRemapToWString(orig_type) -{ -} diff --git a/dtool/src/interrogate/parameterRemapCharStarToString.h b/dtool/src/interrogate/parameterRemapCharStarToString.h deleted file mode 100644 index 8d1d891681..0000000000 --- a/dtool/src/interrogate/parameterRemapCharStarToString.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapCharStarToString.h - * @author drose - * @date 2000-08-09 - */ - -#ifndef PARAMETERREMAPCHARSTARTOSTRING_H -#define PARAMETERREMAPCHARSTARTOSTRING_H - -#include "dtoolbase.h" - -#include "parameterRemapToString.h" - -/** - * Maps from (char *) or (const char *) to the atomic string type. - */ -class ParameterRemapCharStarToString : public ParameterRemapToString { -public: - ParameterRemapCharStarToString(CPPType *orig_type); -}; - -/** - * Maps from (wchar_t *) or (const wchar_ *) to the atomic wide-string type. - */ -class ParameterRemapWCharStarToWString : public ParameterRemapToWString { -public: - ParameterRemapWCharStarToWString(CPPType *orig_type); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapConcreteToPointer.cxx b/dtool/src/interrogate/parameterRemapConcreteToPointer.cxx deleted file mode 100644 index 9f217076cb..0000000000 --- a/dtool/src/interrogate/parameterRemapConcreteToPointer.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapConcreteToPointer.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "parameterRemapConcreteToPointer.h" -#include "interrogate.h" -#include "interrogateBuilder.h" -#include "typeManager.h" - -#include "cppType.h" -#include "cppDeclaration.h" -#include "cppConstType.h" -#include "cppPointerType.h" - -/** - * - */ -ParameterRemapConcreteToPointer:: -ParameterRemapConcreteToPointer(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - _new_type = TypeManager::wrap_pointer(orig_type); -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapConcreteToPointer:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - if (variable_name.size() > 1 && variable_name[0] == '&') { - // Prevent generating something like *¶m Also, if this is really some - // local type, we can presumably just move it? - out << "std::move(" << variable_name.substr(1) << ")"; - } else { - out << "*" << variable_name; - } -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapConcreteToPointer:: -get_return_expr(const std::string &expression) { - return - "new " + _orig_type->get_local_name(&parser) + - "(" + expression + ")"; -} - -/** - * Returns true if the return value represents a value that was newly - * allocated, and hence must be explicitly deallocated later by the caller. - */ -bool ParameterRemapConcreteToPointer:: -return_value_needs_management() { - return true; -} - -/** - * If return_value_needs_management() returns true, this should return the - * index of the function that should be called when it is time to destruct the - * return value. It will generally be the same as the destructor for the - * class we just returned a pointer to. - */ -FunctionIndex ParameterRemapConcreteToPointer:: -get_return_value_destructor() { - return builder.get_destructor_for(_orig_type); -} - -/** - * This is a hack around a problem VC++ has with overly-complex expressions, - * particularly in conjunction with the 'new' operator. If this parameter - * type is one that will probably give VC++ a headache, this should be set - * true to indicate that the code generator should save the return value - * expression into a temporary variable first, and pass the temporary variable - * name in instead. - */ -bool ParameterRemapConcreteToPointer:: -return_value_should_be_simple() { - return true; -} diff --git a/dtool/src/interrogate/parameterRemapConcreteToPointer.h b/dtool/src/interrogate/parameterRemapConcreteToPointer.h deleted file mode 100644 index 2e69597712..0000000000 --- a/dtool/src/interrogate/parameterRemapConcreteToPointer.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapConcreteToPointer.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef PARAMETERREMAPCONCRETETOPOINTER_H -#define PARAMETERREMAPCONCRETETOPOINTER_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that handles remapping a concrete structure or class - * parameter to a pointer parameter. - */ -class ParameterRemapConcreteToPointer : public ParameterRemap { -public: - ParameterRemapConcreteToPointer(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); - virtual bool return_value_needs_management(); - virtual FunctionIndex get_return_value_destructor(); - virtual bool return_value_should_be_simple(); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapConstToNonConst.cxx b/dtool/src/interrogate/parameterRemapConstToNonConst.cxx deleted file mode 100644 index 2fb23e90bc..0000000000 --- a/dtool/src/interrogate/parameterRemapConstToNonConst.cxx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapConstToNonConst.cxx - * @author drose - * @date 2000-08-04 - */ - -#include "parameterRemapConstToNonConst.h" -#include "typeManager.h" - -#include "cppConstType.h" - -/** - * - */ -ParameterRemapConstToNonConst:: -ParameterRemapConstToNonConst(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - _new_type = TypeManager::unwrap_const(orig_type); -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapConstToNonConst:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - out << variable_name; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapConstToNonConst:: -get_return_expr(const std::string &expression) { - return expression; -} diff --git a/dtool/src/interrogate/parameterRemapConstToNonConst.h b/dtool/src/interrogate/parameterRemapConstToNonConst.h deleted file mode 100644 index ee376764e1..0000000000 --- a/dtool/src/interrogate/parameterRemapConstToNonConst.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapConstToNonConst.h - * @author drose - * @date 2000-08-04 - */ - -#ifndef PARAMETERREMAPCONSTTONONCONST_H -#define PARAMETERREMAPCONSTTONONCONST_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that handles remapping a simple const parameter - * (like const int) to an ordinary parameter (like int). It doesn't apply to - * const references or const pointers, however. - */ -class ParameterRemapConstToNonConst : public ParameterRemap { -public: - ParameterRemapConstToNonConst(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapEnumToInt.cxx b/dtool/src/interrogate/parameterRemapEnumToInt.cxx deleted file mode 100644 index 59fb6019fc..0000000000 --- a/dtool/src/interrogate/parameterRemapEnumToInt.cxx +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapEnumToInt.cxx - * @author drose - * @date 2000-08-04 - */ - -#include "parameterRemapEnumToInt.h" -#include "interrogate.h" - -#include "cppSimpleType.h" -#include "cppConstType.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" - -/** - * - */ -ParameterRemapEnumToInt:: -ParameterRemapEnumToInt(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - _new_type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); - _enum_type = unwrap_type(_orig_type); -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapEnumToInt:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - out << "(" << _enum_type->get_local_name(&parser) << ")" << variable_name; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapEnumToInt:: -get_return_expr(const std::string &expression) { - return "(int)(" + expression + ")"; -} - -/** - * Recursively walks through the type definition, and finds the enum - * definition under all the wrappers. - */ -CPPType *ParameterRemapEnumToInt:: -unwrap_type(CPPType *source_type) const { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return unwrap_type(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return unwrap_type(source_type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_pointer: - return unwrap_type(source_type->as_pointer_type()->_pointing_at); - - default: - return source_type; - } -} diff --git a/dtool/src/interrogate/parameterRemapEnumToInt.h b/dtool/src/interrogate/parameterRemapEnumToInt.h deleted file mode 100644 index a74951bcaa..0000000000 --- a/dtool/src/interrogate/parameterRemapEnumToInt.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapEnumToInt.h - * @author drose - * @date 2000-08-04 - */ - -#ifndef PARAMETERREMAPENUMTOINT_H -#define PARAMETERREMAPENUMTOINT_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that handles remapping an enumerated type to an - * integer parameter. - */ -class ParameterRemapEnumToInt : public ParameterRemap { -public: - ParameterRemapEnumToInt(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); - -private: - CPPType *_enum_type; - - CPPType *unwrap_type(CPPType *source_type) const; -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapHandleToInt.cxx b/dtool/src/interrogate/parameterRemapHandleToInt.cxx deleted file mode 100644 index 4594ca45c8..0000000000 --- a/dtool/src/interrogate/parameterRemapHandleToInt.cxx +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapHandleToInt.cxx - * @author rdb - * @date 2015-09-08 - */ - -#include "parameterRemapHandleToInt.h" -#include "interrogate.h" -#include "interrogateBuilder.h" -#include "typeManager.h" - -#include "cppType.h" -#include "cppDeclaration.h" -#include "cppConstType.h" -#include "cppPointerType.h" - -/** - * - */ -ParameterRemapHandleToInt:: -ParameterRemapHandleToInt(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - _new_type = TypeManager::get_int_type(); -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapHandleToInt:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - CPPType *unwrapped = TypeManager::unwrap_const(_orig_type); - - if (unwrapped->get_local_name(&parser) == "TypeHandle") { - out << "TypeHandle::from_index(" << variable_name << ")"; - } else { - out << unwrapped->get_local_name(&parser) << "(" << variable_name << ")"; - } -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapHandleToInt:: -get_return_expr(const std::string &expression) { - return "(" + expression + ").get_index()"; -} diff --git a/dtool/src/interrogate/parameterRemapHandleToInt.h b/dtool/src/interrogate/parameterRemapHandleToInt.h deleted file mode 100644 index 32c2016300..0000000000 --- a/dtool/src/interrogate/parameterRemapHandleToInt.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapHandleToInt.h - * @author rdb - * @date 2015-09-08 - */ - -#ifndef PARAMETERREMAPHANDLETOINT_H -#define PARAMETERREMAPHANDLETOINT_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that handles remapping a Handle parameter to an - * integer. This makes it easier to set up a dynamic typing system on the - * scripting language side. - * - * It also applies to ButtonHandle or any other class with the same semantics, - * because why not. - */ -class ParameterRemapHandleToInt : public ParameterRemap { -public: - ParameterRemapHandleToInt(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapPTToPointer.cxx b/dtool/src/interrogate/parameterRemapPTToPointer.cxx deleted file mode 100644 index 243b907260..0000000000 --- a/dtool/src/interrogate/parameterRemapPTToPointer.cxx +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapPTToPointer.cxx - * @author drose - * @date 2000-08-10 - */ - -#include "parameterRemapPTToPointer.h" -#include "interrogate.h" -#include "interrogateBuilder.h" -#include "typeManager.h" - -#include "cppType.h" -#include "cppStructType.h" -#include "cppDeclaration.h" -#include "pnotify.h" - -using std::string; - -/** - * - */ -ParameterRemapPTToPointer:: -ParameterRemapPTToPointer(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - CPPStructType *pt_type = TypeManager::unwrap(_orig_type)->as_struct_type(); - assert(pt_type != nullptr); - - // A horrible hack around a CPPParser bug. We don't trust the CPPStructType - // pointer we were given; instead, we ask CPPParser to parse a new type of - // the same name. This has a better chance of fully resolving templates. - string name = pt_type->get_local_name(&parser); - CPPType *new_type = parser.parse_type(name); - if (new_type == nullptr) { - nout << "Type " << name << " is unknown to parser.\n"; - } else { - new_type = new_type->resolve_type(&parser, &parser); - pt_type = new_type->as_struct_type(); - assert(pt_type != nullptr); - } - - _pointer_type = TypeManager::get_pointer_type(pt_type); - if (_pointer_type == nullptr) { - // If we couldn't figure out the pointer type, forget it. - nout << "Couldn't figure out pointer type for " << *pt_type << "\n"; - _is_valid = false; - return; - } - - _new_type = _pointer_type; - - // We must use an actual PointerTo to hold any temporary values, until we - // can safely ref it. - _temporary_type = pt_type; -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapPTToPointer:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << variable_name; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapPTToPointer:: -get_return_expr(const string &expression) { - return expression; -} - -/** - * Returns the string that converts the expression stored in the indicated - * temporary variable to the appropriate return value type. This is normally - * a pass-through, but in cases when the temporary variable type must be - * different than the return type (i.e. get_temporary_type() != - * get_new_type()), this might perform some operation. - */ -string ParameterRemapPTToPointer:: -temporary_to_return(const string &temporary) { - return temporary + ".p()"; -} diff --git a/dtool/src/interrogate/parameterRemapPTToPointer.h b/dtool/src/interrogate/parameterRemapPTToPointer.h deleted file mode 100644 index 5c59f075b9..0000000000 --- a/dtool/src/interrogate/parameterRemapPTToPointer.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapPTToPointer.h - * @author drose - * @date 2000-08-10 - */ - -#ifndef PARAMETERREMAPPTTOPOINTER_H -#define PARAMETERREMAPPTTOPOINTER_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -class CPPType; -class CPPStructType; - -/** - * A ParameterRemap class that handles remapping a PT(Type) or PointerTo - * to a Type *. - */ -class ParameterRemapPTToPointer : public ParameterRemap { -public: - ParameterRemapPTToPointer(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); - virtual std::string temporary_to_return(const std::string &temporary); - -private: - CPPType *_pointer_type; -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapReferenceToConcrete.cxx b/dtool/src/interrogate/parameterRemapReferenceToConcrete.cxx deleted file mode 100644 index bdb613cef6..0000000000 --- a/dtool/src/interrogate/parameterRemapReferenceToConcrete.cxx +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapReferenceToConcrete.cxx - * @author drose - * @date 2000-08-04 - */ - -#include "parameterRemapReferenceToConcrete.h" -#include "typeManager.h" - -#include "cppType.h" -#include "cppDeclaration.h" -#include "cppConstType.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" - -/** - * - */ -ParameterRemapReferenceToConcrete:: -ParameterRemapReferenceToConcrete(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - _new_type = TypeManager::unwrap_const_reference(orig_type); -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapReferenceToConcrete:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - out << variable_name; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapReferenceToConcrete:: -get_return_expr(const std::string &expression) { - return expression; -} diff --git a/dtool/src/interrogate/parameterRemapReferenceToConcrete.h b/dtool/src/interrogate/parameterRemapReferenceToConcrete.h deleted file mode 100644 index 12c7ef27bd..0000000000 --- a/dtool/src/interrogate/parameterRemapReferenceToConcrete.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapReferenceToConcrete.h - * @author drose - * @date 2000-08-04 - */ - -#ifndef PARAMETERREMAPREFERENCETOCONCRETE_H -#define PARAMETERREMAPREFERENCETOCONCRETE_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that handles remapping a const reference parameter - * to a concrete. This only makes sense when we're talking about a const - * reference to a simple type. - */ -class ParameterRemapReferenceToConcrete : public ParameterRemap { -public: - ParameterRemapReferenceToConcrete(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapReferenceToPointer.cxx b/dtool/src/interrogate/parameterRemapReferenceToPointer.cxx deleted file mode 100644 index 4e8d1fad90..0000000000 --- a/dtool/src/interrogate/parameterRemapReferenceToPointer.cxx +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapReferenceToPointer.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "parameterRemapReferenceToPointer.h" -#include "typeManager.h" - -#include "cppType.h" -#include "cppDeclaration.h" -#include "cppConstType.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" - -/** - * - */ -ParameterRemapReferenceToPointer:: -ParameterRemapReferenceToPointer(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - _new_type = TypeManager::wrap_pointer(TypeManager::unwrap_reference(orig_type)); -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapReferenceToPointer:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - if (variable_name.size() > 1 && variable_name[0] == '&') { - // Prevent generating something like *¶m Also, if this is really some - // local type, we can presumably just move it? This is only relevant if - // this parameter is an rvalue reference, but CPPParser can't know that, - // and it might have an overload that takes an rvalue reference. It - // shouldn't hurt either way. - out << "std::move(" << variable_name.substr(1) << ")"; - } else { - out << "*" << variable_name; - } -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapReferenceToPointer:: -get_return_expr(const std::string &expression) { - return "&(" + expression + ")"; -} diff --git a/dtool/src/interrogate/parameterRemapReferenceToPointer.h b/dtool/src/interrogate/parameterRemapReferenceToPointer.h deleted file mode 100644 index 6ee71d86c5..0000000000 --- a/dtool/src/interrogate/parameterRemapReferenceToPointer.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapReferenceToPointer.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef PARAMETERREMAPREFERENCETOPOINTER_H -#define PARAMETERREMAPREFERENCETOPOINTER_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that handles remapping a reference (or a const - * reference) parameter to a pointer (or const pointer) parameter. - */ -class ParameterRemapReferenceToPointer : public ParameterRemap { -public: - ParameterRemapReferenceToPointer(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapThis.cxx b/dtool/src/interrogate/parameterRemapThis.cxx deleted file mode 100644 index 7fd8be4243..0000000000 --- a/dtool/src/interrogate/parameterRemapThis.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapThis.cxx - * @author drose - * @date 2000-08-02 - */ - -#include "parameterRemapThis.h" -#include "typeManager.h" - -#include "cppType.h" -#include "cppSimpleType.h" -#include "cppPointerType.h" -#include "cppConstType.h" - -/** - * - */ -ParameterRemapThis:: -ParameterRemapThis(CPPType *type, bool is_const) : - ParameterRemap(TypeManager::get_void_type()) -{ - if (is_const) { - _new_type = TypeManager::wrap_const_pointer(type); - } else { - _new_type = TypeManager::wrap_pointer(type); - } - _orig_type = _new_type; -} - -/** - * Outputs an expression that converts the indicated variable from the new - * type to the original type, for passing into the actual C++ function. - */ -void ParameterRemapThis:: -pass_parameter(std::ostream &out, const std::string &variable_name) { - out << "(*" << variable_name << ")"; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -std::string ParameterRemapThis:: -get_return_expr(const std::string &) { - return "**invalid**"; -} - -/** - * Returns true if this is the "this" parameter. - */ -bool ParameterRemapThis:: -is_this() { - return true; -} diff --git a/dtool/src/interrogate/parameterRemapThis.h b/dtool/src/interrogate/parameterRemapThis.h deleted file mode 100644 index 3d13b66717..0000000000 --- a/dtool/src/interrogate/parameterRemapThis.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapThis.h - * @author drose - * @date 2000-08-02 - */ - -#ifndef PARAMETERREMAPTHIS_H -#define PARAMETERREMAPTHIS_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -class CPPType; - -/** - * A ParameterRemap class that represents a generated "this" parameter. - */ -class ParameterRemapThis : public ParameterRemap { -public: - ParameterRemapThis(CPPType *type, bool is_const); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); - virtual bool is_this(); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapToString.cxx b/dtool/src/interrogate/parameterRemapToString.cxx deleted file mode 100644 index 9771a2db1b..0000000000 --- a/dtool/src/interrogate/parameterRemapToString.cxx +++ /dev/null @@ -1,115 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapToString.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "parameterRemapToString.h" -#include "interrogate.h" -#include "typeManager.h" - -using std::string; - -/** - * - */ -ParameterRemapToString:: -ParameterRemapToString(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - static CPPType *char_star_type = nullptr; - if (char_star_type == nullptr) { - char_star_type = parser.parse_type("char *"); - } - - static CPPType *const_char_star_type = nullptr; - if (const_char_star_type == nullptr) { - const_char_star_type = parser.parse_type("const char *"); - } - - if (TypeManager::is_const_char_pointer(orig_type) || TypeManager::is_string(orig_type)) { - _new_type = const_char_star_type; - } else { - _new_type = char_star_type; - } -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapToString:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << variable_name; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapToString:: -get_return_expr(const string &expression) { - return expression; -} - -/** - * Returns true if the type represented by the conversion is now the atomic - * string type. We have to have this crazy method for representing atomic - * string, because there's no such type in C (and hence no corresponding - * CPPType *). - */ -bool ParameterRemapToString:: -new_type_is_atomic_string() { - return true; -} - -/** - * - */ -ParameterRemapToWString:: -ParameterRemapToWString(CPPType *orig_type) : - ParameterRemap(orig_type) -{ - static CPPType *char_star_type = nullptr; - if (char_star_type == nullptr) { - char_star_type = parser.parse_type("const wchar_t *"); - } - - _new_type = char_star_type; -} - -/** - * Outputs an expression that converts the indicated variable from the - * original type to the new type, for passing into the actual C++ function. - */ -void ParameterRemapToWString:: -pass_parameter(std::ostream &out, const string &variable_name) { - out << variable_name; -} - -/** - * Returns an expression that evalutes to the appropriate value type for - * returning from the function, given an expression of the original type. - */ -string ParameterRemapToWString:: -get_return_expr(const string &expression) { - return expression; -} - -/** - * Returns true if the type represented by the conversion is now the atomic - * string type. We have to have this crazy method for representing atomic - * string, because there's no such type in C (and hence no corresponding - * CPPType *). - */ -bool ParameterRemapToWString:: -new_type_is_atomic_string() { - return true; -} diff --git a/dtool/src/interrogate/parameterRemapToString.h b/dtool/src/interrogate/parameterRemapToString.h deleted file mode 100644 index 5eed97d731..0000000000 --- a/dtool/src/interrogate/parameterRemapToString.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapToString.h - * @author drose - * @date 2000-08-09 - */ - -#ifndef PARAMETERREMAPTOSTRING_H -#define PARAMETERREMAPTOSTRING_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A base class for several different remapping types that convert to an - * atomic string class. - * - * The atomic string class is represented in the C interface as a (const char - * *). Other interfaces may be able to represent it differently, subverting - * the code defined here. - */ -class ParameterRemapToString : public ParameterRemap { -public: - ParameterRemapToString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); - - virtual bool new_type_is_atomic_string(); -}; - -/** - * A base class for several different remapping types that convert to an - * atomic string class. - * - * The atomic string class is represented in the C interface as a (const - * wchar_t *). Other interfaces may be able to represent it differently, - * subverting the code defined here. - */ -class ParameterRemapToWString : public ParameterRemap { -public: - ParameterRemapToWString(CPPType *orig_type); - - virtual void pass_parameter(std::ostream &out, const std::string &variable_name); - virtual std::string get_return_expr(const std::string &expression); - - virtual bool new_type_is_atomic_string(); -}; - -#endif diff --git a/dtool/src/interrogate/parameterRemapUnchanged.cxx b/dtool/src/interrogate/parameterRemapUnchanged.cxx deleted file mode 100644 index a39314166f..0000000000 --- a/dtool/src/interrogate/parameterRemapUnchanged.cxx +++ /dev/null @@ -1,23 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapUnchanged.cxx - * @author drose - * @date 2000-08-01 - */ - -#include "parameterRemapUnchanged.h" - -/** - * - */ -ParameterRemapUnchanged:: -ParameterRemapUnchanged(CPPType *orig_type) : - ParameterRemap(orig_type) -{ -} diff --git a/dtool/src/interrogate/parameterRemapUnchanged.h b/dtool/src/interrogate/parameterRemapUnchanged.h deleted file mode 100644 index 127fd908d8..0000000000 --- a/dtool/src/interrogate/parameterRemapUnchanged.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parameterRemapUnchanged.h - * @author drose - * @date 2000-08-01 - */ - -#ifndef PARAMETERREMAPUNCHANGED_H -#define PARAMETERREMAPUNCHANGED_H - -#include "dtoolbase.h" - -#include "parameterRemap.h" - -/** - * A ParameterRemap class that represents no change to the parameter: the - * parameter type is legal as is. - */ -class ParameterRemapUnchanged : public ParameterRemap { -public: - ParameterRemapUnchanged(CPPType *orig_type); -}; - -#endif diff --git a/dtool/src/interrogate/parse_file.cxx b/dtool/src/interrogate/parse_file.cxx deleted file mode 100644 index 0c92918c53..0000000000 --- a/dtool/src/interrogate/parse_file.cxx +++ /dev/null @@ -1,379 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parse_file.cxx - * @author drose - * @date 1999-10-20 - */ - -#include "cppParser.h" -#include "cppManifest.h" -#include "cppStructType.h" -#include "cppFunctionGroup.h" -#include "cppTypedefType.h" -#include "cppExpressionParser.h" -#include "cppExpression.h" -#include "cppType.h" -#include "cppGlobals.h" -#include "panda_getopt_long.h" -#include "preprocess_argv.h" -#include - -using std::cerr; -using std::cin; -using std::cout; -using std::string; - -CPPParser parser; - -void -predefine_macro(CPPParser &parser, const string &option) { - string macro_name, macro_def; - - size_t eq = option.find('='); - if (eq != string::npos) { - macro_name = option.substr(0, eq); - macro_def = option.substr(eq + 1); - } else { - macro_name = option; - } - - cerr << "Predefining " << macro_name << " as " << macro_def << "\n"; - - CPPManifest *macro = new CPPManifest(parser, macro_name, macro_def); - parser._manifests[macro->_name] = macro; -} - -void -show_type_or_expression(const string &str) { - CPPExpression *expr = parser.parse_expr(str); - if (expr != nullptr) { - cout << "\nExpression: " << *expr << "\n"; - CPPType *type = expr->determine_type(); - if (type == nullptr) { - cout << "type is unknown\n"; - } else { - cout << "type is " << *type << "\n"; - } - cout << "value is " << expr->evaluate() << "\n\n"; - - } else { - CPPType *type = parser.parse_type(str); - if (type != nullptr) { - cout << "\nType: " << *type << "\n" - << "Defined in: " << type->_file << "\n" - << "Subtype code is: " << (int)type->get_subtype() << "\n\n"; - - CPPStructType *stype = type->as_struct_type(); - if (stype != nullptr) { - stype->check_virtual(); - } - - type->output(cout, 0, &parser, true); - cout << "\n\n" - << "is_template = " << type->is_template() << "\n" - << "is_fully_specified = " << type->is_fully_specified() << "\n" - << "is_tbd = " << type->is_tbd() << "\n" - << "is_fundamental = " << type->is_fundamental() << "\n" - << "is_standard_layout = " << type->is_standard_layout() << "\n" - << "is_trivial = " << type->is_trivial() << "\n" - << "is_trivially_copyable = " << type->is_trivially_copyable() << "\n" - << "is_default_constructible = " << type->is_default_constructible() << "\n" - << "is_copy_constructible = " << type->is_copy_constructible() << "\n" - << "is_copy_assignable = " << type->is_copy_assignable() << "\n" - << "is_destructible = " << type->is_destructible() << "\n"; - if (type->has_typedef_name()) { - cout << "get_typedef_name = " << type->get_typedef_name() << "\n"; - } - cout << "get_simple_name = " << type->get_simple_name() << "\n" - << "get_local_name = " << type->get_local_name() << "\n" - << "get_fully_scoped_name = " << type->get_fully_scoped_name() << "\n" - << "get_preferred_name = " << type->get_preferred_name() << "\n" - << "is_incomplete = " << type->is_incomplete() << "\n"; - - if (stype != nullptr) { - cout << "scope = " << stype->get_scope()->get_fully_scoped_name() << "\n"; - bool is_abstract = stype->is_abstract(); - cout << "is_abstract = " << is_abstract << "\n"; - if (is_abstract) { - cout << "pure virtual functions:\n"; - CPPStructType::VFunctions vf; - stype->get_pure_virtual_funcs(vf); - CPPStructType::VFunctions::const_iterator fi; - for (fi = vf.begin(); fi != vf.end(); ++fi) { - cout << " " << *(*fi) << "\n"; - } - } - } - - cout << "\n"; - } else { - cout << "Invalid expression or type.\n"; - } - } -} - -void -show_methods(const string &str) { - CPPType *type = parser.parse_type(str); - if (type == nullptr) { - cerr << "Invalid type: " << str << "\n"; - return; - } - - CPPStructType *stype = type->as_struct_type(); - if (stype == nullptr) { - cerr << "Type is not a structure or class.\n"; - return; - } - - CPPScope *scope = stype->get_scope(); - assert(scope != nullptr); - - cerr << "Methods in " << *stype << ":\n"; - - CPPScope::Functions::const_iterator fi; - for (fi = scope->_functions.begin(); fi != scope->_functions.end(); ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - cerr << " " << *inst << "\n"; - } - } -} - -void -show_data_members(const string &str) { - CPPType *type = parser.parse_type(str); - if (type == nullptr) { - cerr << "Invalid type: " << str << "\n"; - return; - } - - CPPStructType *stype = type->as_struct_type(); - if (stype == nullptr) { - cerr << "Type is not a structure or class.\n"; - return; - } - - CPPScope *scope = stype->get_scope(); - assert(scope != nullptr); - - cerr << "Data members in " << *stype << ":\n"; - - CPPScope::Variables::const_iterator vi; - for (vi = scope->_variables.begin(); vi != scope->_variables.end(); ++vi) { - CPPInstance *inst = (*vi).second; - cerr << " " << *inst << "\n"; - } -} - -void -show_nested_types(const string &str) { - CPPType *type = parser.parse_type(str); - if (type == nullptr) { - cerr << "Invalid type: " << str << "\n"; - return; - } - - CPPStructType *stype = type->as_struct_type(); - if (stype == nullptr) { - cerr << "Type is not a structure or class.\n"; - return; - } - - CPPScope *scope = stype->get_scope(); - assert(scope != nullptr); - - cerr << "Nested types in " << *stype << ":\n"; - - CPPScope::Types::const_iterator ti; - for (ti = scope->_types.begin(); ti != scope->_types.end(); ++ti) { - CPPType *tp = (*ti).second; - cerr << " " << *tp << "\n"; - } -} - - -int -main(int argc, char **argv) { - extern char *optarg; - extern int optind; - const char *optstr = "I:S:D:o:l:vpE"; - preprocess_argv(argc, argv); - - parser.set_verbose(2); - bool prompt = false; - bool preprocess = false; - - int flag = getopt(argc, argv, optstr); - - while (flag != EOF) { - switch (flag) { - case 'I': - parser._quote_include_path.append_directory(optarg); - parser._quote_include_kind.push_back(CPPFile::S_alternate); - break; - - case 'S': - parser._angle_include_path.append_directory(optarg); - parser._quote_include_path.append_directory(optarg); - parser._quote_include_kind.push_back(CPPFile::S_system); - break; - - case 'D': - predefine_macro(parser, optarg); - break; - - case 'o': - cerr << "Ignoring output file " << optarg << "\n"; - break; - - case 'l': - cpp_longlong_keyword = optarg; - break; - - case 'v': - parser.set_verbose(parser.get_verbose() + 1); - break; - - case 'p': - prompt = true; - break; - - case 'E': - preprocess = true; - break; - - default: - exit(1); - } - flag = getopt(argc, argv, optstr); - } - - argc -= (optind-1); - argv += (optind-1); - - - if (argc < 2) { - cerr << "parse-file [opts] file1.h [file2.h ... ]\n" - << "\nOptions:\n\n" - << " -I include_path\n" - << " -S system_include_path\n" - << " -D manifest_name\n" - << " -D manifest_name=manifest_definition\n" - << " -o output_file (ignored)\n" - << " -v (increase verbosity)\n" - << " -E (output preprocessed token stream)\n" - << " -p (prompt for expression instead of dumping output)\n"; - - exit(1); - } - - for (int i = 1; i < argc; i++) { - if (preprocess) { - if (!parser.preprocess_file(argv[i])) { - cerr << "Error in preprocessing.\n"; - exit(1); - } - } else { - if (!parser.parse_file(argv[i])) { - cerr << "Error in parsing.\n"; - exit(1); - } - } - } - - cerr << "Finished parsing.\n"; - - if (prompt) { - while (cin) { - string str; - cout << "Enter an expression or type name:\n"; - std::getline(std::cin, str); - if (!str.empty()) { - - size_t space = str.find(' '); - if (space != string::npos) { - string first_word = str.substr(0, space); - string remainder = str.substr(space + 1); - - if (first_word == "methods") { - show_methods(remainder); - } else if (first_word == "members") { - show_data_members(remainder); - } else if (first_word == "types") { - show_nested_types(remainder); - } else { - show_type_or_expression(str); - } - } else { - show_type_or_expression(str); - } - } - } - } else { - parser.write(cout, 0, &parser); - cout << "\n"; - } - - /* - cout << "Opened the following files:\n"; - CPPParser::ParsedFiles::const_iterator fi; - for (fi = parser._parsed_files.begin(); - fi != parser._parsed_files.end(); - ++fi) { - cout << " "; - - switch ((*fi)._source) { - case CPPFile::S_local: - cout << "L"; - break; - case CPPFile::S_alternate: - cout << "A"; - break; - case CPPFile::S_system: - cout << "S"; - break; - default: - cout << " "; - } - - cout << " " << (*fi) << "\n"; - } - */ - - /* - CPPParser::Comments::const_iterator ci; - for (ci = parser._comments.begin(); ci != parser._comments.end(); ++ci) { - const CPPParser::CommentBlock &c = (*ci); - cout << "Comment in file " << c._file << " at line " << c._line_number - << ":\n" << c._comment << "\n\n"; - } - */ - - /* - CPPParser::Manifests::const_iterator mi; - for (mi = parser._manifests.begin(); mi != parser._manifests.end(); ++mi) { - const CPPManifest *m = (*mi).second; - cout << "Manifest " << m->_name << " defined in " << m->_file; - CPPType *type = m->determine_type(); - if (type == (CPPType *)NULL) { - cout << " (no type)\n"; - } else { - cout << " has type " << *type << "\n"; - } - } - */ - - return (0); -} diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx deleted file mode 100644 index dc5d6679de..0000000000 --- a/dtool/src/interrogate/typeManager.cxx +++ /dev/null @@ -1,2614 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file typeManager.cxx - * @author drose - * @date 2000-08-14 - */ - -#include "typeManager.h" -#include "interrogate.h" - -#include "cppArrayType.h" -#include "cppConstType.h" -#include "cppEnumType.h" -#include "cppFunctionGroup.h" -#include "cppFunctionType.h" -#include "cppIdentifier.h" -#include "cppParameterList.h" -#include "cppPointerType.h" -#include "cppReferenceType.h" -#include "cppSimpleType.h" -#include "cppStructType.h" -#include "cppTemplateScope.h" -#include "cppTypeDeclaration.h" -#include "cppTypedefType.h" -#include "pnotify.h" - -using std::string; - -/** - * A horrible hack around a CPPParser bug. We don't trust the CPPType pointer - * we were given; instead, we ask CPPParser to parse a new type of the same - * name. This has a better chance of fully resolving templates. - */ -CPPType *TypeManager:: -resolve_type(CPPType *type, CPPScope *scope) { - if (scope == nullptr) { - scope = &parser; - } - - //CPPType *orig_type = type; - type = type->resolve_type(scope, &parser); - string name = type->get_local_name(&parser); - if (name.empty()) { - // Don't try to resolve unnamed types. - return type; - } - - // I think I fixed the bug; no need for the below hack any more. - return type; - -/* - CPPType *new_type = parser.parse_type(name); - if (new_type == (CPPType *)NULL) { - nout << "Type \"" << name << "\" (from " << *orig_type << ") is unknown to parser.\n"; - } else { - type = new_type->resolve_type(&parser, &parser); - } - - return type; -*/ -} - -/** - * Returns true if the indicated type is something we can legitimately assign - * a value to, or false otherwise. - */ -bool TypeManager:: -is_assignable(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - case CPPDeclaration::ST_reference: - case CPPDeclaration::ST_extension: - return false; - - case CPPDeclaration::ST_struct: - // In many cases, this is assignable, but there are some bizarre cases - // where it is not. Particularly in the event that the programmer has - // defined a private copy assignment operator for the class or struct. - - // We could try to figure out whether this has happened, but screw it. - // Concrete structure objects are not assignable, and so they don't get - // setters synthesized for them. If you want a setter, write it yourself. - - // We'll make an exception for the string types, however, since these are - // nearly an atomic type. - if (is_basic_string_char(type) || is_basic_string_wchar(type)) { - return true; - } - - return false; - - case CPPDeclaration::ST_typedef: - return is_assignable(type->as_typedef_type()->_type); - - default: - return true; - } -} - -/** - * Returns true if the indicated type is some kind of a reference or const - * reference type to something useful, false otherwise. - */ -bool TypeManager:: -is_reference(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_reference(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_pointable(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_reference(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is some kind of an rvalue reference. - */ -bool TypeManager:: -is_rvalue_reference(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_rvalue_reference(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return type->as_reference_type()->_value_category == CPPReferenceType::VC_rvalue; - - case CPPDeclaration::ST_typedef: - return is_rvalue_reference(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is some kind of a reference or const - * reference type at all, false otherwise. - */ -bool TypeManager:: -is_ref_to_anything(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_ref_to_anything(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return true; - - case CPPDeclaration::ST_typedef: - return is_ref_to_anything(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const reference to something, false - * otherwise. - */ -bool TypeManager:: -is_const_ref_to_anything(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_const_ref_to_anything(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_const(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ref_to_anything(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const pointer to something, false - * otherwise. - */ -bool TypeManager:: -is_const_pointer_to_anything(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_const_pointer_to_anything(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_const(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_pointer_to_anything(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a non-const pointer or reference to - * something, false otherwise. - */ -bool TypeManager:: -is_const_pointer_or_ref(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_const_pointer_or_ref(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_const(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_reference: - return is_const(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_pointer_or_ref(type->as_typedef_type()->_type); - - case CPPDeclaration::ST_struct: - if (type->get_simple_name() == "PointerTo") { - return false; - } else if (type->get_simple_name() == "ConstPointerTo") { - return true; - } - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a non-const pointer or reference to - * something, false otherwise. - */ -bool TypeManager:: -is_non_const_pointer_or_ref(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_non_const_pointer_or_ref(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return !is_const(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_reference: - return !is_const(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_non_const_pointer_or_ref(type->as_typedef_type()->_type); - - case CPPDeclaration::ST_struct: - if (type->get_simple_name() == "PointerTo") { - return true; - } else if (type->get_simple_name() == "ConstPointerTo") { - return false; - } - - default: - return false; - } -} - -/** - * Returns true if the indicated type is some kind of a pointer or const - * pointer type, false otherwise. - */ -bool TypeManager:: -is_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_pointable(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is some kind of a const type, false - * otherwise. - */ -bool TypeManager:: -is_const(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return true; - - case CPPDeclaration::ST_typedef: - return is_const(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a concrete struct, class, or union - * type, or false otherwise. - */ -bool TypeManager:: -is_struct(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_struct(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_struct: - case CPPDeclaration::ST_extension: - return true; - - case CPPDeclaration::ST_typedef: - return is_struct(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is an enum class, const or otherwise. - */ -bool TypeManager:: -is_scoped_enum(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_enum: - return ((CPPEnumType *)type)->is_scoped(); - - case CPPDeclaration::ST_const: - return is_scoped_enum(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_scoped_enum(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is some kind of enumerated type, const - * or otherwise. - */ -bool TypeManager:: -is_enum(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_enum: - return true; - - case CPPDeclaration::ST_const: - return is_enum(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_enum(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const enumerated type. - */ -bool TypeManager:: -is_const_enum(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_enum(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_enum(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const reference to an enumerated - * type. - */ -bool TypeManager:: -is_const_ref_to_enum(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_const_enum(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ref_to_enum(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is nullptr_t, possibly const or a - * typedef to it. - */ -bool TypeManager:: -is_nullptr(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_simple: - return type->as_simple_type()->_type == CPPSimpleType::T_nullptr; - - case CPPDeclaration::ST_const: - return is_nullptr(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_nullptr(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is something that a scripting language - * can handle directly as a concrete, like an int or float, either const or - * non-const. - */ -bool TypeManager:: -is_simple(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_simple: - case CPPDeclaration::ST_enum: - return !is_void(type); - - case CPPDeclaration::ST_const: - return is_simple(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_simple(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const wrapper around some simple - * type like int. - */ -bool TypeManager:: -is_const_simple(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_simple(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_const_simple(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const reference to something that a - * scripting language can handle directly as a concrete. - */ -bool TypeManager:: -is_const_ref_to_simple(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_const_simple(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ref_to_simple(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a non-const reference to something - * that a scripting language can handle directly as a concrete. - */ -bool TypeManager:: -is_ref_to_simple(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_simple(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_ref_to_simple(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is an array of a simple type. - */ -bool TypeManager:: -is_simple_array(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_simple_array(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_array: - return is_simple(type->as_array_type()->_element_type); - - case CPPDeclaration::ST_typedef: - return is_simple_array(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const or a non-constant pointer to - * a simple type. This could also be a reference to an array of the simple - * type. - */ -bool TypeManager:: -is_pointer_to_simple(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_simple(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_simple(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_array: - return is_simple(type->as_array_type()->_element_type); - - case CPPDeclaration::ST_reference: - return is_pointer_to_simple(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pointer_to_simple(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is something ordinary that a scripting - * language can handle a pointer to, e.g. a class or a structure, but not an - * int or a function. - */ -bool TypeManager:: -is_pointable(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointable(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_extension: - return (type->as_extension_type()->_type != CPPExtensionType::T_enum); - - case CPPDeclaration::ST_struct: - return true; - - // case CPPDeclaration::ST_simple: return is_char(type); - - case CPPDeclaration::ST_typedef: - return is_pointable(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is char or const char, but not signed or - * unsigned char. - */ -bool TypeManager:: -is_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return - simple_type->_type == CPPSimpleType::T_char && - simple_type->_flags == 0; - } - } - - case CPPDeclaration::ST_typedef: - return is_char(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is unsigned char, but not signed or - * 'plain' char. - */ -bool TypeManager:: -is_unsigned_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_unsigned_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - - if (simple_type != nullptr) { - return - (simple_type->_type == CPPSimpleType::T_char) && - (simple_type->_flags & CPPSimpleType::F_unsigned) != 0; - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_unsigned_char(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is signed char, but not unsigned or - * 'plain' char. - */ -bool TypeManager:: -is_signed_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_signed_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - - if (simple_type != nullptr) { - return - (simple_type->_type == CPPSimpleType::T_char) && - (simple_type->_flags & CPPSimpleType::F_signed) != 0; - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_signed_char(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is char * or const char * or some such. - */ -bool TypeManager:: -is_char_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_char_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_char(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_char_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is const char*. - */ -bool TypeManager:: -is_const_char_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_const_char_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return (is_const(type->as_pointer_type()->_pointing_at) && - is_char(type->as_pointer_type()->_pointing_at)); - - case CPPDeclaration::ST_typedef: - return is_const_char_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is unsigned char* or const unsigned - * char*. - */ -bool TypeManager:: -is_unsigned_char_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_unsigned_char_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_unsigned_char(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_unsigned_char_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is const unsigned char*. - */ -bool TypeManager:: -is_const_unsigned_char_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_unsigned_char_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_const_unsigned_char_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the type is basic_string. This is the standard C++ - * string class. - */ -bool TypeManager:: -is_basic_string_char(CPPType *type) { - CPPType *string_type = get_basic_string_char_type(); - if (string_type != nullptr && - string_type->get_local_name(&parser) == type->get_local_name(&parser)) { - return true; - } - - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_basic_string_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_basic_string_char(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is a const wrapper around - * basic_string. - */ -bool TypeManager:: -is_const_basic_string_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_basic_string_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_const_basic_string_char(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const reference to - * basic_string. - */ -bool TypeManager:: -is_const_ref_to_basic_string_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_const_basic_string_char(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ref_to_basic_string_char(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const pointer to - * basic_string. - */ -bool TypeManager:: -is_const_ptr_to_basic_string_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_pointer: - return is_const_basic_string_char(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ptr_to_basic_string_char(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the type is basic_string, or a const reference to it. - */ -bool TypeManager:: -is_string(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_const_basic_string_char(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_string(type->as_typedef_type()->_type); - - default: - break; - } - - return is_basic_string_char(type); -} - -/** - * Returns true if the indicated type is wchar_t or const wchar_t. We don't - * mind signed or unsigned wchar_t. - */ -bool TypeManager:: -is_wchar(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_wchar(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return simple_type->_type == CPPSimpleType::T_wchar_t; - } - } - - case CPPDeclaration::ST_typedef: - return is_wchar(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is wchar_t * or const wchar_t * or some - * such. - */ -bool TypeManager:: -is_wchar_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_wchar_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_wchar(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_wchar_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the type is basic_string. This is the standard - * C++ wide string class. - */ -bool TypeManager:: -is_basic_string_wchar(CPPType *type) { - CPPType *string_type = get_basic_string_wchar_type(); - if (string_type != nullptr && - string_type->get_local_name(&parser) == type->get_local_name(&parser)) { - return true; - } - - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_basic_string_wchar(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_basic_string_wchar(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is a const wrapper around - * basic_string. - */ -bool TypeManager:: -is_const_basic_string_wchar(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_basic_string_wchar(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_const_basic_string_wchar(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const reference to - * basic_string. - */ -bool TypeManager:: -is_const_ref_to_basic_string_wchar(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_const_basic_string_wchar(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ref_to_basic_string_wchar(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const pointer to - * basic_string. - */ -bool TypeManager:: -is_const_ptr_to_basic_string_wchar(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_pointer: - return is_const_basic_string_wchar(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ptr_to_basic_string_wchar(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the type is basic_string, or a const reference to - * it. - */ -bool TypeManager:: -is_wstring(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_reference: - return is_const_basic_string_wchar(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_wstring(type->as_typedef_type()->_type); - - default: - break; - } - - return is_basic_string_wchar(type); -} - -/** - * Returns true if the type is vector, or a const reference to - * it. - */ -bool TypeManager:: -is_vector_unsigned_char(CPPType *type) { - if (type->get_local_name(&parser) == "vector< unsigned char >" || - type->get_local_name(&parser) == "std::vector< unsigned char >" || - type->get_local_name(&parser) == "pvector< unsigned char >") { - return true; - } - - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_vector_unsigned_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_const_vector_unsigned_char(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_struct: - { - CPPStructType *stype = type->as_struct_type(); - CPPStructType::Derivation::const_iterator di; - for (di = stype->_derivation.begin(); - di != stype->_derivation.end(); - ++di) { - if (is_vector_unsigned_char((*di)._base)) { - return true; - } - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_vector_unsigned_char(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is a const wrapper around - * vector. - */ -bool TypeManager:: -is_const_vector_unsigned_char(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_vector_unsigned_char(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_const_vector_unsigned_char(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is bool, or some trivial variant. - */ -bool TypeManager:: -is_bool(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_bool(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return - simple_type->_type == CPPSimpleType::T_bool; - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_bool(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is one of the basic integer types: bool, - * char, short, int, or long, signed or unsigned, as well as enumerated types. - */ -bool TypeManager:: -is_integer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_integer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_enum: - return true; - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return - (simple_type->_type == CPPSimpleType::T_bool || - simple_type->_type == CPPSimpleType::T_char || - simple_type->_type == CPPSimpleType::T_wchar_t || - simple_type->_type == CPPSimpleType::T_char8_t || - simple_type->_type == CPPSimpleType::T_char16_t || - simple_type->_type == CPPSimpleType::T_char32_t || - simple_type->_type == CPPSimpleType::T_int); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_integer(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is one of the basic integer types, but - * only the unsigned varieties. - */ -bool TypeManager:: -is_unsigned_integer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_unsigned_integer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return - ((simple_type->_type == CPPSimpleType::T_bool || - simple_type->_type == CPPSimpleType::T_char || - simple_type->_type == CPPSimpleType::T_wchar_t || - simple_type->_type == CPPSimpleType::T_int) && - (simple_type->_flags & CPPSimpleType::F_unsigned) != 0) || - (simple_type->_type == CPPSimpleType::T_char8_t || - simple_type->_type == CPPSimpleType::T_char16_t || - simple_type->_type == CPPSimpleType::T_char32_t); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_unsigned_integer(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is the "size_t" type, or a const size_t, - * or a typedef to either. - */ -bool TypeManager:: -is_size(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_size(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - if (type->get_simple_name() == "size_t") { - return is_integer(type->as_typedef_type()->_type); - } else { - return is_size(type->as_typedef_type()->_type); - } - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is the "ssize_t" type, or a const - * ssize_t, or a typedef to either. ptrdiff_t and streamsize are also - * accepted, since they are usually also defined as the signed counterpart to - * size_t. - */ -bool TypeManager:: -is_ssize(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_ssize(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - if (type->get_simple_name() == "Py_ssize_t" || - type->get_simple_name() == "ssize_t" || - type->get_simple_name() == "ptrdiff_t" || - type->get_simple_name() == "streamsize") { - return is_integer(type->as_typedef_type()->_type); - } else { - return is_ssize(type->as_typedef_type()->_type); - } - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is the "long" type, whether signed or - * unsigned. - */ -bool TypeManager:: -is_long(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_long(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return (simple_type->_type == CPPSimpleType::T_int && - (simple_type->_flags & CPPSimpleType::F_long) != 0); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_long(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is the "short" type, whether signed or - * unsigned. - */ -bool TypeManager:: -is_short(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_short(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return (simple_type->_type == CPPSimpleType::T_int && - (simple_type->_flags & CPPSimpleType::F_short) != 0); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_short(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is an unsigned "short" type. - */ -bool TypeManager:: -is_unsigned_short(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_unsigned_short(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return (simple_type->_type == CPPSimpleType::T_int && - (simple_type->_flags & (CPPSimpleType::F_short | CPPSimpleType::F_unsigned)) == (CPPSimpleType::F_short | CPPSimpleType::F_unsigned)); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_unsigned_short(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is the "long long" type or larger, or at - * least a 64-bit integer, whether signed or unsigned. - */ -bool TypeManager:: -is_longlong(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_longlong(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return (simple_type->_type == CPPSimpleType::T_int && - (simple_type->_flags & CPPSimpleType::F_longlong) != 0); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_longlong(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is an unsigned "long long" type or - * larger, or at least a 64-bit unsigned integer. - */ -bool TypeManager:: -is_unsigned_longlong(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_unsigned_longlong(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return (simple_type->_type == CPPSimpleType::T_int && - (simple_type->_flags & (CPPSimpleType::F_longlong | CPPSimpleType::F_unsigned)) == (CPPSimpleType::F_longlong | CPPSimpleType::F_unsigned)); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_unsigned_longlong(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is the "double" type. - */ -bool TypeManager:: -is_double(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_double(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return (simple_type->_type == CPPSimpleType::T_double); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_double(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is one of the basic floating-point - * types: float, double, or some similar variant. - */ -bool TypeManager:: -is_float(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_float(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_simple: - { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return - (simple_type->_type == CPPSimpleType::T_float || - simple_type->_type == CPPSimpleType::T_double); - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_float(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is void. (Not void *, just void.) - */ -bool TypeManager:: -is_void(CPPType *type) { - CPPSimpleType *simple_type = type->as_simple_type(); - if (simple_type != nullptr) { - return - simple_type->_type == CPPSimpleType::T_void && - simple_type->_flags == 0; - } - - return false; -} - -/** - * Returns true if the indicated type is some class that derives from - * ReferenceCount, or defines ref and unref(), or false otherwise. - */ -bool TypeManager:: -is_reference_count(CPPType *type) { - CPPType *refcount_type = get_reference_count_type(); - if (refcount_type != nullptr && - refcount_type->get_local_name(&parser) == type->get_local_name(&parser)) { - return true; - } - - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_reference_count(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_struct: - { - CPPStructType *stype = type->as_struct_type(); - - // If we have methods named ref() and unref(), this is good enough. - if (stype->_scope->_functions.count("ref") && - stype->_scope->_functions.count("unref") && - stype->_scope->_functions.count("get_ref_count")) { - return true; - } - - CPPStructType::Derivation::const_iterator di; - for (di = stype->_derivation.begin(); - di != stype->_derivation.end(); - ++di) { - if (is_reference_count((*di)._base)) { - return true; - } - } - } - break; - - case CPPDeclaration::ST_typedef: - return is_reference_count(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is a pointer to a class that derives - * from ReferenceCount. - */ -bool TypeManager:: -is_reference_count_pointer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_reference_count_pointer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_reference_count(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_reference_count_pointer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is some class that derives from - * PointerToBase, or false otherwise. - */ -bool TypeManager:: -is_pointer_to_base(CPPType *type) { - // We only check the simple name of the type against PointerToBase, since we - // need to allow for the various template instantiations of this thing. - - // We also check explicitly for "PointerTo" and "ConstPointerTo", instead of - // actually checking for PointerToBase, because we don't want to consider - // PointerToArray in this category. - if (type->get_simple_name() == "PointerTo" || - type->get_simple_name() == "ConstPointerTo") { - return true; - } - - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_base(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_struct: - { - CPPStructType *stype = type->as_struct_type(); - CPPStructType::Derivation::const_iterator di; - for (di = stype->_derivation.begin(); - di != stype->_derivation.end(); - ++di) { - if (is_pointer_to_base((*di)._base)) { - return true; - } - } - } - return false; - - case CPPDeclaration::ST_typedef: - return is_pointer_to_base(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const PointerToBase or some - * derivative. - */ -bool TypeManager:: -is_const_pointer_to_base(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_base(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return is_const_pointer_to_base(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is a const reference to a class that - * derives from PointerToBase. - */ -bool TypeManager:: -is_const_ref_to_pointer_to_base(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_reference(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_const_pointer_to_base(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_const_ref_to_pointer_to_base(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the type is pair<>, or a reference to it. - */ -bool TypeManager:: -is_pair(CPPType *type) { - // We only check the simple name of the type against pair, since we need to - // allow for the various template instantiations of this thing. - if (type->get_simple_name() == "pair") { - return true; - } - - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pair(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_pair(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pair(type->as_typedef_type()->_type); - - default: - break; - } - - return false; -} - -/** - * Returns true if the indicated type is PyObject *. - */ -bool TypeManager:: -is_pointer_to_PyObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_PyObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_PyObject(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pointer_to_PyObject(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyObject. - */ -bool TypeManager:: -is_PyObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_PyObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_extension: - case CPPDeclaration::ST_struct: - return (type->get_local_name(&parser) == "_object" || - type->get_local_name(&parser) == "_typeobject"); - - case CPPDeclaration::ST_typedef: - return (is_struct(type->as_typedef_type()->_type) && - (type->get_local_name(&parser) == "PyObject" || - type->get_local_name(&parser) == "PyTypeObject" || - type->get_local_name(&parser) == "PyStringObject" || - type->get_local_name(&parser) == "PyUnicodeObject")) || - is_PyObject(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyTypeObject *. - */ -bool TypeManager:: -is_pointer_to_PyTypeObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_PyTypeObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_PyTypeObject(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pointer_to_PyTypeObject(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyTypeObject. - */ -bool TypeManager:: -is_PyTypeObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_PyTypeObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_extension: - case CPPDeclaration::ST_struct: - return (type->get_local_name(&parser) == "_typeobject"); - - case CPPDeclaration::ST_typedef: - return (type->get_local_name(&parser) == "PyTypeObject" && - is_struct(type->as_typedef_type()->_type)) || - is_PyTypeObject(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyStringObject *. - */ -bool TypeManager:: -is_pointer_to_PyStringObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_PyStringObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_PyStringObject(type->as_pointer_type()->_pointing_at); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyStringObject. - */ -bool TypeManager:: -is_PyStringObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_PyStringObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return (type->get_local_name(&parser) == "PyStringObject" && - is_struct(type->as_typedef_type()->_type)) || - is_PyStringObject(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyStringObject *. - */ -bool TypeManager:: -is_pointer_to_PyUnicodeObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_PyUnicodeObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_PyUnicodeObject(type->as_pointer_type()->_pointing_at); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyUnicodeObject. - */ -bool TypeManager:: -is_PyUnicodeObject(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_PyUnicodeObject(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_typedef: - return (type->get_local_name(&parser) == "PyUnicodeObject" && - is_struct(type->as_typedef_type()->_type)) || - is_PyUnicodeObject(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is Py_buffer *. - */ -bool TypeManager:: -is_pointer_to_Py_buffer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_Py_buffer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return is_Py_buffer(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pointer_to_Py_buffer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is Py_buffer. - */ -bool TypeManager:: -is_Py_buffer(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_Py_buffer(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_extension: - case CPPDeclaration::ST_struct: - return (type->get_local_name(&parser) == "Py_buffer" || - type->get_local_name(&parser) == "bufferinfo"); - - case CPPDeclaration::ST_typedef: - return is_Py_buffer(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is TypeHandle or a class with identical - * semantics like ButtonHandle. - */ -bool TypeManager:: -is_handle(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_handle(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_extension: - case CPPDeclaration::ST_struct: - return (type->get_local_name(&parser) == "TypeHandle" || - type->get_local_name(&parser) == "ButtonHandle"); - - case CPPDeclaration::ST_typedef: - return is_handle(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyObject. - */ -bool TypeManager::is_ostream(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_ostream(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_struct: - return (type->get_local_name(&parser) == "std::ostream" || - type->get_local_name(&parser) == "ostream" || - type->get_local_name(&parser) == "std::basic_ostream< char >"); - - case CPPDeclaration::ST_typedef: - return is_ostream(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the indicated type is PyObject *. - */ -bool TypeManager:: -is_pointer_to_ostream(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_pointer_to_ostream(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_ostream(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_pointer: - return is_ostream(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return is_pointer_to_ostream(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns true if the type is an unpublished type, e.g. a protected or - * private nested class, or simply a type not marked as 'published', or if the - * type is a pointer or reference to such an unpublished type, or even if the - * type is a function type that includes a parameter of such an unpublished - * type. - */ -bool TypeManager:: -involves_unpublished(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return involves_unpublished(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return involves_unpublished(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_pointer: - return involves_unpublished(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_struct: - // A struct type is unpublished only if all of its members are - // unpublished. - if (type->_declaration != nullptr) { - if (type->_declaration->_vis <= min_vis) { - return false; - } - } - { - CPPScope *scope = type->as_struct_type()->_scope; - - bool any_exported = false; - CPPScope::Declarations::const_iterator di; - for (di = scope->_declarations.begin(); - di != scope->_declarations.end() && !any_exported; - ++di) { - if ((*di)->_vis <= min_vis) { - any_exported = true; - } - } - - return !any_exported; - } - - case CPPDeclaration::ST_function: - if (type->_declaration != nullptr) { - if (type->_declaration->_vis <= min_vis) { - return false; - } - } - return true; - /* - { - CPPFunctionType *ftype = type->as_function_type(); - if (involves_unpublished(ftype->_return_type)) { - return true; - } - const CPPParameterList::Parameters ¶ms = - ftype->_parameters->_parameters; - CPPParameterList::Parameters::const_iterator pi; - for (pi = params.begin(); pi != params.end(); ++pi) { - if (involves_unpublished((*pi)->_type)) { - return true; - } - } - return false; - } - */ - - case CPPDeclaration::ST_typedef: - return involves_unpublished(type->as_typedef_type()->_type); - - default: - if (type->_declaration != nullptr) { - return (type->_declaration->_vis > min_vis); - } - return false; - } -} - -/** - * Returns true if the type is an protected type, e.g. a protected or private - * nested class, or if the type is a pointer or reference to such a protected - * type, or even if the type is a function type that includes a parameter of - * such a protected type. - */ -bool TypeManager:: -involves_protected(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return involves_protected(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return involves_protected(type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_pointer: - return involves_protected(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_function: - { - CPPFunctionType *ftype = type->as_function_type(); - if (involves_protected(ftype->_return_type)) { - return true; - } - const CPPParameterList::Parameters ¶ms = - ftype->_parameters->_parameters; - CPPParameterList::Parameters::const_iterator pi; - for (pi = params.begin(); pi != params.end(); ++pi) { - if (involves_protected((*pi)->_type)) { - return true; - } - } - return false; - } - - case CPPDeclaration::ST_typedef: - return involves_protected(type->as_typedef_type()->_type); - - default: - if (type->_declaration != nullptr) { - return (type->_declaration->_vis > V_public); - } - return false; - } -} - -/** - * Returns true if the type involves an rvalue reference. - */ -bool TypeManager:: -involves_rvalue_reference(CPPType *type) { - switch (type->get_subtype()) { - case CPPDeclaration::ST_const: - return involves_rvalue_reference(type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return type->as_reference_type()->_value_category == CPPReferenceType::VC_rvalue; - - case CPPDeclaration::ST_pointer: - return involves_rvalue_reference(type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_function: - { - CPPFunctionType *ftype = type->as_function_type(); - if (involves_rvalue_reference(ftype->_return_type)) { - return true; - } - const CPPParameterList::Parameters ¶ms = - ftype->_parameters->_parameters; - CPPParameterList::Parameters::const_iterator pi; - for (pi = params.begin(); pi != params.end(); ++pi) { - if (involves_rvalue_reference((*pi)->_type)) { - return true; - } - } - return false; - } - - case CPPDeclaration::ST_typedef: - return involves_rvalue_reference(type->as_typedef_type()->_type); - - default: - return false; - } -} - -/** - * Returns the type this pointer type points to. - */ -CPPType *TypeManager:: -unwrap_pointer(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return unwrap_pointer(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_pointer: - return source_type->as_pointer_type()->_pointing_at; - - default: - return source_type; - } -} - -/** - * Returns the type this reference type points to. - */ -CPPType *TypeManager:: -unwrap_reference(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return unwrap_reference(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return source_type->as_reference_type()->_pointing_at; - - default: - return source_type; - } -} - -/** - * Removes the const declaration from the outside of the type. - */ -CPPType *TypeManager:: -unwrap_const(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return unwrap_const(source_type->as_const_type()->_wrapped_around); - - default: - return source_type; - } -} - -/** - * Removes a reference or a const reference from the type. - */ -CPPType *TypeManager:: -unwrap_const_reference(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return unwrap_const_reference(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return unwrap_const(source_type->as_reference_type()->_pointing_at); - - default: - return source_type; - } -} - -/** - * Removes all const, pointer, reference wrappers, and typedefs, to get to the - * thing we're talking about. - */ -CPPType *TypeManager:: -unwrap(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return unwrap(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return unwrap(source_type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_pointer: - return unwrap(source_type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_typedef: - return unwrap(source_type->as_typedef_type()->_type); - - default: - return source_type; - } -} - -/** - * Returns the type of pointer the given PointerTo class emulates. - * Essentially this just checks the return type of the method called 'p()'. - * Returns NULL if the PointerTo class has no method p(). - */ -CPPType *TypeManager:: -get_pointer_type(CPPStructType *pt_type) { - CPPScope *scope = pt_type->_scope; - - CPPScope::Functions::const_iterator fi; - fi = scope->_functions.find("p"); - if (fi != scope->_functions.end()) { - CPPFunctionGroup *fgroup = (*fi).second; - - // These are all the functions named "p". Now look for one that takes no - // parameters. - CPPFunctionGroup::Instances::iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *function = (*ii); - CPPFunctionType *ftype = function->_type->as_function_type(); - assert(ftype != nullptr); - if (ftype->_parameters->_parameters.empty()) { - // Here's the function p(). What's its return type? - return resolve_type(ftype->_return_type); - } - } - } - - return nullptr; -} - -/** - * Returns the ith template parameter type. For instance, if the type is - * pair, then this function will return type A when passing 0 and type B - * when passing 1, and NULL otherwise. - */ -CPPType *TypeManager:: -get_template_parameter_type(CPPType *source_type, int i) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return get_template_parameter_type(source_type->as_const_type()->_wrapped_around, i); - - case CPPDeclaration::ST_reference: - return get_template_parameter_type(source_type->as_reference_type()->_pointing_at, i); - - case CPPDeclaration::ST_typedef: - return get_template_parameter_type(source_type->as_typedef_type()->_type); - - default: - break; - } - - CPPStructType *type = source_type->as_struct_type(); - if (type == nullptr) { - return nullptr; - } - - // I'm not sure how reliable this is, but I don't know if there is a more - // proper way to access this. - CPPTemplateParameterList *templ = type->_ident->_names.back().get_templ(); - if (templ == nullptr || i >= (int)templ->_parameters.size()) { - return nullptr; - } - - CPPDeclaration *decl = templ->_parameters[i]; - return decl->as_type(); -} - -/** - * Returns the type corresponding to a pointer to the given type. - */ -CPPType *TypeManager:: -wrap_pointer(CPPType *source_type) { - return CPPType::new_type(new CPPPointerType(source_type)); -} - -/** - * Returns the type corresponding to a const pointer to the given type. - */ -CPPType *TypeManager:: -wrap_const_pointer(CPPType *source_type) { - if (source_type->as_const_type() != nullptr) { - // It's already const. - return - CPPType::new_type(new CPPPointerType(source_type)); - } else { - return - CPPType::new_type(new CPPPointerType(new CPPConstType(source_type))); - } -} - -/** - * Returns the type corresponding to a const reference to the given type. - */ -CPPType *TypeManager:: -wrap_const_reference(CPPType *source_type) { - if (source_type->as_const_type() != nullptr) { - // It's already const. - return - CPPType::new_type(new CPPReferenceType(source_type)); - } else { - return - CPPType::new_type(new CPPReferenceType(new CPPConstType(source_type))); - } -} - -/** - * Returns a CPPType that represents basic_string, or NULL if the type - * is unknown. - */ -CPPType *TypeManager:: -get_basic_string_char_type() { - static bool got_type = false; - static CPPType *type = nullptr; - if (!got_type) { - type = parser.parse_type("std::basic_string"); - got_type = true; - } - return type; -} - -/** - * Returns a CPPType that represents basic_string, or NULL if the - * type is unknown. - */ -CPPType *TypeManager:: -get_basic_string_wchar_type() { - static bool got_type = false; - static CPPType *type = nullptr; - if (!got_type) { - type = parser.parse_type("std::basic_string"); - got_type = true; - } - return type; -} - -/** - * Returns a CPPType that represents ReferenceCount, or NULL if the type is - * unknown. - */ -CPPType *TypeManager:: -get_reference_count_type() { - static bool got_type = false; - static CPPType *type = nullptr; - if (!got_type) { - type = parser.parse_type("ReferenceCount"); - got_type = true; - } - return type; -} - -/** - * Returns a CPPType that represents void. - */ -CPPType *TypeManager:: -get_void_type() { - static bool got_type = false; - static CPPType *type = nullptr; - if (!got_type) { - type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_void)); - got_type = true; - } - return type; -} - -/** - * Returns a CPPType that represents int. - */ -CPPType *TypeManager:: -get_int_type() { - static bool got_type = false; - static CPPType *type = nullptr; - if (!got_type) { - type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); - got_type = true; - } - return type; -} - -/** - * Returns a string corresponding to the given function signature. This is a - * unique string per each uniquely-callable C++ function or method. Basically - * it's the function prototype, sans the return type. - * - * If num_default_parameters is nonzero, it is the number of parameters to - * omit from the end of the parameter list. This in effect gets the function - * signature for an equivalent function with n parameters assuming default - * values. - */ -string TypeManager:: -get_function_signature(CPPInstance *function, - int num_default_parameters) { - CPPFunctionType *ftype = function->_type->as_function_type(); - assert(ftype != nullptr); - - std::ostringstream out; - - // It's tempting to mark static methods with a different function signature - // than non-static, because a static method doesn't have an implicit 'this' - // parameter. However, this breaks the lookup when we come across a method - // definition outside of the class body; since there's no clue at this point - // whether the method is static or not, we can't successfully look it up. - // Bummer. - /* - if ((function->_storage_class & CPPInstance::SC_static) != 0) { - out << "static "; - } - */ - - out << function->get_local_name(&parser) << "("; - - const CPPParameterList::Parameters ¶ms = - ftype->_parameters->_parameters; - CPPParameterList::Parameters::const_iterator pi; - - int num_params = params.size() - num_default_parameters; - pi = params.begin(); - for (int n = 0; n < num_params; n++) { - assert(pi != params.end()); - CPPType *ptype = (*pi)->_type; - - // One exception: if the type is a const reference to something, we build - // the signature with its corresponding concrete. C++ can't differentiate - // these two anyway. - if (is_const_ref_to_anything(ptype)) { - ptype = unwrap_const_reference(ptype); - } - - out << ptype->get_local_name(&parser); - - if (n + 1 < num_params) { - out << ", "; - } - - ++pi; - } - out << ")"; - - if (ftype->_flags & CPPFunctionType::F_const_method) { - out << " const"; - } - - return out.str(); -} - -/** - * Returns a string corresponding to the given function name. This is not - * necessarily unique to the particular overloaded function instance, but is - * common among all overloaded functions of the same name. - */ -string TypeManager:: -get_function_name(CPPInstance *function) { - return function->get_local_name(&parser); -} - -/** - * Returns true if the destructor for the given class or struct is protected - * or private, or false if the destructor is public or absent. - */ -bool TypeManager:: -has_protected_destructor(CPPType *type) { - CPPStructType *struct_type = type->as_struct_type(); - if (struct_type == nullptr) { - // It's not even a struct type! - return false; - } - - CPPScope *scope = struct_type->get_scope(); - - // Look for the destructor. - CPPScope::Declarations::const_iterator di; - for (di = scope->_declarations.begin(); - di != scope->_declarations.end(); - ++di) { - if ((*di)->get_subtype() == CPPDeclaration::ST_instance) { - CPPInstance *inst = (*di)->as_instance(); - if (inst->_type->get_subtype() == CPPDeclaration::ST_function) { - // Here's a function declaration. - CPPFunctionType *ftype = inst->_type->as_function_type(); - assert(ftype != nullptr); - if ((ftype->_flags & CPPFunctionType::F_destructor) != 0) { - // Here's the destructor! Is it protected? - return (inst->_vis > V_public); - } - } - } - } - - // No explicit destructor. - return false; -} -/** - * - */ -bool TypeManager:: -is_exported(CPPType *in_type) { - string name = in_type->get_local_name(&parser); - if (name.empty()) { - return false; - } - - // this question is about the base type - CPPType *base_type = resolve_type(unwrap(in_type)); - // CPPType *base_type = in_type; Ok export Rules.. Classes and Structs and - // Unions are exported only if they have a function that is exported.. - // function is the easiest case. - - if (base_type->_vis <= min_vis) { - return true; - } - - if (in_type->_vis <= min_vis) { - return true; - } - - if (base_type->get_subtype() == CPPDeclaration::ST_struct) { - CPPStructType *struct_type = base_type->resolve_type(&parser, &parser)->as_struct_type(); - CPPScope *scope = struct_type->_scope; - - CPPScope::Declarations::const_iterator di; - for (di = scope->_declarations.begin(); - di != scope->_declarations.end(); ++di) { - if ((*di)->_vis <= min_vis) { - return true; - } - } - - } else if (base_type->get_subtype() == CPPDeclaration::ST_instance) { - CPPInstance *inst = base_type->as_instance(); - if (inst->_type->get_subtype() == CPPDeclaration::ST_function) { - CPPInstance *function = inst; - CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type(); - if (ftype->_vis <= min_vis) { - return true; - } - } else { - if (inst->_vis <= min_vis) { - return true; - } - } - - } else if (base_type->get_subtype() == CPPDeclaration::ST_typedef) { - CPPTypedefType *tdef = base_type->as_typedef_type(); - if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) { - CPPStructType *struct_type =tdef->_type->resolve_type(&parser, &parser)->as_struct_type(); - return is_exported(struct_type); - } - - } else if (base_type->get_subtype() == CPPDeclaration::ST_type_declaration) { - CPPType *type = base_type->as_type_declaration()->_type; - if (type->get_subtype() == CPPDeclaration::ST_struct) { - CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); - // CPPScope *scope = struct_type->_scope; - return is_exported(struct_type); - - } else if (type->get_subtype() == CPPDeclaration::ST_enum) { - // CPPEnumType *enum_type = type->as_type()->resolve_type(&parser, - // &parser)->as_enum_type(); - if (type->_vis <= min_vis) { - return true; - } - } - } - -/* - printf("---------------------> Visibility Failed %s %d Vis=%d, Minvis=%d\n", - base_type->get_fully_scoped_name().c_str(), - base_type->get_subtype(), - base_type->_vis, - min_vis); -*/ - return false; -} - -/** - * Returns true if the type is defined in a local file rather than one that is - * included. - */ -bool TypeManager:: -is_local(CPPType *source_type) { - switch (source_type->get_subtype()) { - case CPPDeclaration::ST_const: - return is_local(source_type->as_const_type()->_wrapped_around); - - case CPPDeclaration::ST_reference: - return is_local(source_type->as_reference_type()->_pointing_at); - - case CPPDeclaration::ST_pointer: - return is_local(source_type->as_pointer_type()->_pointing_at); - - case CPPDeclaration::ST_simple: - return false; - - default: - { - CPPType *resolved_type = resolve_type(source_type); - if (resolved_type->_file._source == CPPFile::S_local && !resolved_type->is_incomplete()) { - return true; - } - } - } - - return false; - - /* - - if (base_type->get_subtype() == CPPDeclaration::ST_struct) - { - CPPStructType *struct_type = base_type->as_struct_type(); - if (struct_type->_file._source == CPPFile::S_local) - return true; - - } - else if (base_type->get_subtype() == CPPDeclaration::ST_instance) - { - CPPInstance *inst = base_type->as_instance(); - if (inst->_type->get_subtype() == CPPDeclaration::ST_function) - { - CPPInstance *function = inst; - CPPFunctionType *ftype = function->_type->resolve_type(&parser, &parser)->as_function_type(); - if (ftype->_file._source == CPPFile::S_local) - return true; - } - else - { - if (inst->_file._source == CPPFile::S_local) - return true; - } - } - else if (base_type->get_subtype() == CPPDeclaration::ST_typedef) - { - CPPTypedef *tdef = base_type->as_typedef(); - if (tdef->_type->get_subtype() == CPPDeclaration::ST_struct) - { - CPPStructType *struct_type =tdef->_type->resolve_type(&parser, &parser)->as_struct_type(); - return IsLocal(struct_type); - - - } - } - else if (base_type->get_subtype() == CPPDeclaration::ST_type_declaration) - { - CPPType *type = base_type->as_type_declaration()->_type; - if (type->get_subtype() == CPPDeclaration::ST_struct) - { - CPPStructType *struct_type =type->as_type()->resolve_type(&parser, &parser)->as_struct_type(); - if (struct_type->_file._source == CPPFile::S_local) - return true; - - } - else if (type->get_subtype() == CPPDeclaration::ST_enum) - { - CPPEnumType *enum_type = type->as_type()->resolve_type(&parser, &parser)->as_enum_type(); - if (enum_type->_file._source != CPPFile::S_local) - return true; - } - } - - if (base_type->_file._source == CPPFile::S_local) - return true; - - return false; - */ -} diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h deleted file mode 100644 index e9161dbd31..0000000000 --- a/dtool/src/interrogate/typeManager.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file typeManager.h - * @author drose - * @date 2000-08-14 - */ - -#ifndef TYPEMANAGER_H -#define TYPEMANAGER_H - -#include "dtoolbase.h" - -class CPPFunctionGroup; -class CPPInstance; -class CPPType; -class CPPSimpleType; -class CPPPointerType; -class CPPConstType; -class CPPExtensionType; -class CPPStructType; -class CPPEnumType; -class CPPFunctionType; -class CPPScope; -class CPPIdentifier; -class CPPNameComponent; -class CPPManifest; - -/** - * This is just a collection of static methods that perform useful operations - * on CPPTypes for interrogate. The class is really just a namespace that - * groups these functions together. - */ -class TypeManager { -public: - - static CPPType *resolve_type(CPPType *type, CPPScope *scope = nullptr); - - static bool is_assignable(CPPType *type); - - static bool is_reference(CPPType *type); - static bool is_rvalue_reference(CPPType *type); - static bool is_ref_to_anything(CPPType *type); - static bool is_const_ref_to_anything(CPPType *type); - static bool is_const_pointer_to_anything(CPPType *type); - static bool is_const_pointer_or_ref(CPPType *type); - static bool is_non_const_pointer_or_ref(CPPType *type); - static bool is_pointer(CPPType *type); - static bool is_const(CPPType *type); - static bool is_struct(CPPType *type); - static bool is_scoped_enum(CPPType *type); - static bool is_enum(CPPType *type); - static bool is_const_enum(CPPType *type); - static bool is_const_ref_to_enum(CPPType *type); - static bool is_nullptr(CPPType *type); - static bool is_simple(CPPType *type); - static bool is_const_simple(CPPType *type); - static bool is_const_ref_to_simple(CPPType *type); - static bool is_ref_to_simple(CPPType *type); - static bool is_simple_array(CPPType *type); - static bool is_pointer_to_simple(CPPType *type); - static bool is_pointable(CPPType *type); - static bool is_char(CPPType *type); - static bool is_unsigned_char(CPPType *type); - static bool is_signed_char(CPPType *type); - static bool is_char_pointer(CPPType *type); - static bool is_const_char_pointer(CPPType *type); - static bool is_unsigned_char_pointer(CPPType *type); - static bool is_const_unsigned_char_pointer(CPPType *type); - static bool is_basic_string_char(CPPType *type); - static bool is_const_basic_string_char(CPPType *type); - static bool is_const_ref_to_basic_string_char(CPPType *type); - static bool is_const_ptr_to_basic_string_char(CPPType *type); - static bool is_string(CPPType *type); - static bool is_wchar(CPPType *type); - static bool is_wchar_pointer(CPPType *type); - static bool is_basic_string_wchar(CPPType *type); - static bool is_const_basic_string_wchar(CPPType *type); - static bool is_const_ref_to_basic_string_wchar(CPPType *type); - static bool is_const_ptr_to_basic_string_wchar(CPPType *type); - static bool is_wstring(CPPType *type); - static bool is_vector_unsigned_char(CPPType *type); - static bool is_const_vector_unsigned_char(CPPType *type); - static bool is_pair(CPPType *type); - static bool is_bool(CPPType *type); - static bool is_integer(CPPType *type); - static bool is_unsigned_integer(CPPType *type); - static bool is_size(CPPType *type); - static bool is_ssize(CPPType *type); - static bool is_long(CPPType *type); - static bool is_short(CPPType *type); - static bool is_unsigned_short(CPPType *type); - static bool is_longlong(CPPType *type); - static bool is_unsigned_longlong(CPPType *type); - static bool is_double(CPPType *type); - static bool is_float(CPPType *type); - static bool is_void(CPPType *type); - static bool is_reference_count(CPPType *type); - static bool is_reference_count_pointer(CPPType *type); - static bool is_pointer_to_base(CPPType *type); - static bool is_const_pointer_to_base(CPPType *type); - static bool is_const_ref_to_pointer_to_base(CPPType *type); - static bool is_pointer_to_PyObject(CPPType *type); - static bool is_PyObject(CPPType *type); - static bool is_pointer_to_PyTypeObject(CPPType *type); - static bool is_PyTypeObject(CPPType *type); - static bool is_pointer_to_PyStringObject(CPPType *type); - static bool is_PyStringObject(CPPType *type); - static bool is_pointer_to_PyUnicodeObject(CPPType *type); - static bool is_PyUnicodeObject(CPPType *type); - static bool is_pointer_to_Py_buffer(CPPType *type); - static bool is_Py_buffer(CPPType *type); - static bool is_handle(CPPType *type); - static bool involves_unpublished(CPPType *type); - static bool involves_protected(CPPType *type); - static bool involves_rvalue_reference(CPPType *type); - - static bool is_ostream(CPPType *type); - static bool is_pointer_to_ostream(CPPType *type); - - static CPPType *unwrap_pointer(CPPType *type); - static CPPType *unwrap_reference(CPPType *type); - static CPPType *unwrap_const(CPPType *type); - static CPPType *unwrap_const_reference(CPPType *type); - static CPPType *unwrap(CPPType *type); - - static CPPType *get_pointer_type(CPPStructType *pt_type); - static CPPType *get_template_parameter_type(CPPType *type, int i = 0); - - static CPPType *wrap_pointer(CPPType *type); - static CPPType *wrap_const_pointer(CPPType *type); - static CPPType *wrap_const_reference(CPPType *type); - - static CPPType *get_basic_string_char_type(); - static CPPType *get_basic_string_wchar_type(); - static CPPType *get_reference_count_type(); - static CPPType *get_void_type(); - static CPPType *get_int_type(); - - static std::string get_function_signature(CPPInstance *function, - int num_default_parameters = 0); - - static std::string get_function_name(CPPInstance *function); - - static bool has_protected_destructor(CPPType *type); - - - static bool is_exported(CPPType *type); - static bool is_local(CPPType *type); -}; - -#endif diff --git a/dtool/src/test_interrogate/test_interrogate.cxx b/dtool/src/test_interrogate/test_interrogate.cxx deleted file mode 100644 index a518f12cc4..0000000000 --- a/dtool/src/test_interrogate/test_interrogate.cxx +++ /dev/null @@ -1,615 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file test_interrogate.cxx - * @author drose - * @date 1999-12-09 - */ - -#include "dtoolbase.h" - -#include "interrogate_interface.h" -#include "interrogate_request.h" -#include "load_dso.h" -#include "filename.h" -#include "panda_getopt.h" -#include "preprocess_argv.h" - -#include - -using std::cerr; -using std::cout; -using std::ostream; -using std::string; - -static ostream & -indent(ostream &out, int indent_level) { - for (int i = 0; i < indent_level; i++) { - out << ' '; - } - return out; -} - -// Indents one or more lines of text, breaking the text up at newline -// characters. -static ostream & -hanging_indent(ostream &out, const string &text, int first_indent_level, - int next_indent_level = -1) { - if (next_indent_level < 0) { - next_indent_level = first_indent_level; - } - - size_t start = 0; - size_t newline = text.find('\n'); - int indent_level = first_indent_level; - while (newline != string::npos) { - indent(out, indent_level) - << text.substr(start, newline - start) << "\n"; - start = newline + 1; - newline = text.find('\n', start); - indent_level = next_indent_level; - } - indent(out, indent_level) - << text.substr(start) << "\n"; - - return out; -} - -void -show_type(int type, bool verbose = false) { - cout << interrogate_type_name(type) << " "; - if (verbose) { - if (strcmp(interrogate_type_name(type), - interrogate_type_true_name(type)) != 0) { - cout << "(" << interrogate_type_true_name(type) << ") "; - } - } - cout << "(" << type << ")"; -} - -void -show_function(int function) { - cout << interrogate_function_scoped_name(function) << " (" << function << ")"; -} - -void -describe_wrapper(int wrapper, int indent_level) { - indent(cout, indent_level) - << "Wrapper (" << wrapper << ")"; - - if (interrogate_wrapper_has_return_value(wrapper)) { - cout << " returns "; - show_type(interrogate_wrapper_return_type(wrapper)); - } else { - cout << " no return value"; - } - - int num_params = interrogate_wrapper_number_of_parameters(wrapper); - cout << ", "; - if (num_params == 0) { - cout << "no parameters.\n"; - } else if (num_params == 1) { - cout << "1 parameter:\n"; - } else { - cout << num_params << " parameters:\n"; - } - - for (int i = 0; i < num_params; i++) { - indent(cout, indent_level + 4); - if (interrogate_wrapper_parameter_is_this(wrapper, i)) { - cout << "*"; - } else { - cout << i; - } - cout << ": "; - show_type(interrogate_wrapper_parameter_type(wrapper, i)); - if (interrogate_wrapper_parameter_has_name(wrapper, i)) { - cout << " '" << interrogate_wrapper_parameter_name(wrapper, i) << "'"; - } else { - cout << " (no name)"; - } - cout << "\n"; - } - - if (interrogate_wrapper_has_comment(wrapper)) { - string comment = interrogate_wrapper_comment(wrapper); - hanging_indent(cout, comment, indent_level + 2); - } - - - if (interrogate_wrapper_caller_manages_return_value(wrapper)) { - indent(cout, indent_level + 2) - << "Caller manages return value using "; - show_function(interrogate_wrapper_return_value_destructor(wrapper)); - cout << "\n"; - } - - indent(cout, indent_level + 2) - << "Wrapper name: " << interrogate_wrapper_name(wrapper); - if (interrogate_wrapper_is_callable_by_name(wrapper)) { - cout << " (callable)"; - } - cout << "\n"; - if (interrogate_wrapper_has_pointer(wrapper)) { - indent(cout, indent_level + 2) - << "Has pointer: " << interrogate_wrapper_pointer(wrapper) << "\n"; - } - string unique_name = interrogate_wrapper_unique_name(wrapper); - indent(cout, indent_level + 2) - << "Unique name is " << unique_name; - int reverse_lookup = interrogate_get_wrapper_by_unique_name(unique_name.c_str()); - if (reverse_lookup == 0) { - cout << " (no reverse lookup)"; - } else if (reverse_lookup != wrapper) { - cout << " (*** reverse lookup returns " << reverse_lookup << "! ***)"; - } - cout << "\n"; -} - -void -describe_function(int function, int indent_level) { - indent(cout, indent_level) - << "Function " << interrogate_function_scoped_name(function) - << " (" << function << ")\n"; - - indent(cout, indent_level + 2) - << "In C: "; - hanging_indent(cout, interrogate_function_prototype(function), - 0, indent_level + 2 + 6); - - if (interrogate_function_is_method(function)) { - indent(cout, indent_level + 2) - << "Method of "; - show_type(interrogate_function_class(function)); - cout << "\n"; - } - - if (interrogate_function_is_virtual(function)) { - indent(cout, indent_level + 2) << "is virtual.\n"; - } - - int w; - - int num_c_wrappers = interrogate_function_number_of_c_wrappers(function); - if (num_c_wrappers == 0) { - } else if (num_c_wrappers == 1) { - indent(cout, indent_level + 2) - << "1 C-style wrapper:\n"; - } else { - indent(cout, indent_level + 2) - << num_c_wrappers << " C-style wrappers:\n"; - } - for (w = 0; w < num_c_wrappers; w++) { - describe_wrapper(interrogate_function_c_wrapper(function, w), - indent_level + 4); - } - - int num_python_wrappers = - interrogate_function_number_of_python_wrappers(function); - if (num_python_wrappers == 0) { - } else if (num_python_wrappers == 1) { - indent(cout, indent_level + 2) - << "1 Python-style wrapper:\n"; - } else { - indent(cout, indent_level + 2) - << num_python_wrappers << " Python-style wrappers:\n"; - } - for (w = 0; w < num_python_wrappers; w++) { - describe_wrapper(interrogate_function_python_wrapper(function, w), - indent_level + 4); - } -} - -void -describe_make_seq(int make_seq, int indent_level) { - indent(cout, indent_level) - << "MakeSeq " << interrogate_make_seq_seq_name(make_seq) - << " (" << make_seq << "): " - << interrogate_make_seq_num_name(make_seq) - << ", " << interrogate_make_seq_element_name(make_seq) - << "\n"; -} - -void -report_manifests() { - int num_manifests = interrogate_number_of_manifests(); - cout << "\n" << num_manifests << " manifests:\n"; - for (int i = 0; i < num_manifests; i++) { - int manifest = interrogate_get_manifest(i); - - cout << " Manifest " << interrogate_manifest_name(manifest); - if (interrogate_manifest_has_type(manifest)) { - cout << " of type "; - show_type(interrogate_manifest_get_type(manifest)); - cout << "\n"; - } else { - cout << " of unknown type\n"; - } - cout << " definition is \"" - << interrogate_manifest_definition(manifest) << "\"\n"; - - if (interrogate_manifest_has_getter(manifest)) { - cout << " value getter: "; - show_function(interrogate_manifest_getter(manifest)); - cout << "\n"; - } - - if (interrogate_manifest_has_int_value(manifest)) { - cout << " int value = " - << interrogate_manifest_get_int_value(manifest) - << "\n"; - } - } -} - -void -describe_element(int element, int indent_level) { - indent(cout, indent_level) - << "Element " << interrogate_element_scoped_name(element) - << " of type "; - show_type(interrogate_element_type(element)); - cout << "\n"; - - if (interrogate_element_has_getter(element)) { - indent(cout, indent_level + 2) - << "Getter is "; - show_function(interrogate_element_getter(element)); - cout << "\n"; - } - - if (interrogate_element_has_setter(element)) { - indent(cout, indent_level + 2) - << "Setter is "; - show_function(interrogate_element_setter(element)); - cout << "\n"; - } -} - -void -report_globals() { - int num_globals = interrogate_number_of_globals(); - cout << "\n" << num_globals << " globals:\n"; - for (int i = 0; i < num_globals; i++) { - describe_element(interrogate_get_global(i), 2); - } -} - -void -describe_type(int type, int indent_level) { - indent(cout, indent_level) << "Type "; - show_type(type, true); - cout << "\n"; - - if (interrogate_type_has_comment(type)) { - string comment = interrogate_type_comment(type); - hanging_indent(cout, comment, indent_level + 2); - } - - if (interrogate_type_is_nested(type)) { - indent(cout, indent_level + 2) - << "Nested within "; - show_type(interrogate_type_outer_class(type)); - cout << "\n"; - } - if (interrogate_type_is_atomic(type)) { - indent(cout, indent_level + 2) - << "atomic " << (int)interrogate_type_atomic_token(type) << "\n"; - } - if (interrogate_type_is_unsigned(type)) { - indent(cout, indent_level + 2) - << "unsigned\n"; - } - if (interrogate_type_is_signed(type)) { - indent(cout, indent_level + 2) - << "signed\n"; - } - if (interrogate_type_is_long(type)) { - indent(cout, indent_level + 2) - << "long\n"; - } - if (interrogate_type_is_longlong(type)) { - indent(cout, indent_level + 2) - << "long long\n"; - } - if (interrogate_type_is_short(type)) { - indent(cout, indent_level + 2) - << "short\n"; - } - if (interrogate_type_is_wrapped(type)) { - indent(cout, indent_level + 2) - << "wrapped "; - show_type(interrogate_type_wrapped_type(type)); - cout << "\n"; - } - if (interrogate_type_is_pointer(type)) { - indent(cout, indent_level + 2) - << "pointer\n"; - } - if (interrogate_type_is_const(type)) { - indent(cout, indent_level + 2) - << "const\n"; - } - if (interrogate_type_is_fully_defined(type)) { - indent(cout, indent_level + 2) - << "fully defined\n"; - } - if (interrogate_type_is_unpublished(type)) { - indent(cout, indent_level + 2) - << "undefined because unpublished\n"; - } - if (interrogate_type_is_enum(type)) { - indent(cout, indent_level + 2) - << "is enum type\n"; - } - if (interrogate_type_is_struct(type)) { - indent(cout, indent_level + 2) - << "is struct type\n"; - } - if (interrogate_type_is_class(type)) { - indent(cout, indent_level + 2) - << "is class type\n"; - } - if (interrogate_type_is_union(type)) { - indent(cout, indent_level + 2) - << "is union type\n"; - } - int num_enum_values = interrogate_type_number_of_enum_values(type); - if (num_enum_values > 0) { - for (int i = 0; i < num_enum_values; i++) { - indent(cout, indent_level + 4) - << interrogate_type_enum_value_name(type, i) - << " = " << interrogate_type_enum_value(type, i) << "\n"; - } - } - int num_constructors = interrogate_type_number_of_constructors(type); - if (num_constructors > 0) { - indent(cout, indent_level + 2) - << num_constructors << " constructors:\n"; - for (int i = 0; i < num_constructors; i++) { - describe_function(interrogate_type_get_constructor(type, i), 6); - } - } - if (interrogate_type_has_destructor(type)) { - indent(cout, indent_level + 2) - << "destructor:\n"; - describe_function(interrogate_type_get_destructor(type), 6); - } - int num_casts = interrogate_type_number_of_casts(type); - if (num_casts > 0) { - indent(cout, indent_level + 2) - << num_casts << " casts:\n"; - for (int i = 0; i < num_casts; i++) { - describe_function(interrogate_type_get_cast(type, i), 6); - } - } - int num_methods = interrogate_type_number_of_methods(type); - if (num_methods > 0) { - indent(cout, indent_level + 2) - << num_methods << " methods:\n"; - for (int i = 0; i < num_methods; i++) { - describe_function(interrogate_type_get_method(type, i), 6); - } - } - int num_make_seqs = interrogate_type_number_of_make_seqs(type); - if (num_make_seqs > 0) { - indent(cout, indent_level + 2) - << num_make_seqs << " make_seqs:\n"; - for (int i = 0; i < num_make_seqs; i++) { - describe_make_seq(interrogate_type_get_make_seq(type, i), 6); - } - } - int num_elements = interrogate_type_number_of_elements(type); - if (num_elements > 0) { - indent(cout, indent_level + 2) - << num_elements << " elements:\n"; - for (int i = 0; i < num_elements; i++) { - describe_element(interrogate_type_get_element(type, i), indent_level + 2); - } - } - int num_derivations = interrogate_type_number_of_derivations(type); - if (num_derivations > 0) { - indent(cout, indent_level + 2) - << num_derivations << " derivations:\n"; - for (int i = 0; i < num_derivations; i++) { - int derivation = interrogate_type_get_derivation(type, i); - indent(cout, indent_level + 4); - show_type(derivation); - if (interrogate_type_derivation_has_upcast(type, i)) { - cout << " (has upcast)"; - } - if (interrogate_type_derivation_downcast_is_impossible(type, i)) { - cout << " (downcast is impossible)"; - } - if (interrogate_type_derivation_has_downcast(type, i)) { - cout << " (has downcast)"; - } - cout << "\n"; - /* - if (interrogate_type_derivation_has_upcast(type, i)) { - describe_function(interrogate_type_get_upcast(type, i), 8); - } - if (interrogate_type_derivation_has_downcast(type, i)) { - describe_function(interrogate_type_get_downcast(type, i), 8); - } - */ - } - } - int num_nested_types = interrogate_type_number_of_nested_types(type); - if (num_nested_types > 0) { - indent(cout, indent_level + 2) - << num_nested_types << " nested types:\n"; - for (int i = 0; i < num_nested_types; i++) { - indent(cout, indent_level + 4); - show_type(interrogate_type_get_nested_type(type, i)); - cout << "\n"; - } - } -} - -void -report_global_types() { - int num_types = interrogate_number_of_global_types(); - cout << "\n" << num_types << " global types:\n"; - - for (int i = 0; i < num_types; i++) { - int type = interrogate_get_global_type(i); - describe_type(type, 2); - } -} - -void -report_global_functions() { - int num_functions = interrogate_number_of_global_functions(); - cout << "\n" << num_functions << " global functions:\n"; - for (int i = 0; i < num_functions; i++) { - int function = interrogate_get_global_function(i); - describe_function(function, 2); - } -} - -void -report_all_types() { - int num_types = interrogate_number_of_types(); - cout << "\n" << num_types << " total types:\n"; - - for (int i = 0; i < num_types; i++) { - int type = interrogate_get_type(i); - describe_type(type, 2); - } -} - -void -report_all_functions() { - int num_functions = interrogate_number_of_functions(); - cout << "\n" << num_functions << " total functions:\n"; - for (int i = 0; i < num_functions; i++) { - int function = interrogate_get_function(i); - describe_function(function, 2); - } -} - -void -usage() { - cerr << - "\n" - "test_interrogate [opts] libfile.so [libfile.so ...]\n\n" - - "Loads the given shared library or libraries, if possible, and reports the\n" - "symbols, types, and functions available within those libraries as reported\n" - "by interrogate.\n\n" - - "In lieu of loading a shared library, you may also read the interrogate\n" - "database file directly by specifying a filename like libfile.in. This will\n" - "report the symbols defined in that file only (without pulling in dependent\n" - "files), and will not have any function pointers available.\n\n" - - "Options:\n\n" - " -p [path]\n" - " Specify the search path for *.in files. This option may be repeated.\n" - " -f Give a detailed report of each function in the database, including\n" - " synthesized functions like upcasts and downcasts.\n" - " -t Give a detailed report of every type in the database, including types\n" - " like pointers and const pointers.\n" - " -q Quickly load up each shared library, if possible, and then immediately\n" - " exit. Useful for quickly determining whether a library can even load.\n\n"; -} - -int -main(int argc, char **argv) { - extern char *optarg; - extern int optind; - const char *optstr = "p:ftqh"; - - bool all_functions = false; - bool all_types = false; - bool quick_load = false; - preprocess_argv(argc, argv); - int flag = getopt(argc, argv, optstr); - - while (flag != EOF) { - switch (flag) { - case 'p': - interrogate_add_search_path(optarg); - break; - - case 'f': - all_functions = true; - break; - - case 't': - all_types = true; - break; - - case 'q': - quick_load = true; - break; - - case 'h': - usage(); - exit(0); - - default: - exit(1); - } - flag = getopt(argc, argv, optstr); - } - - argc -= (optind-1); - argv += (optind-1); - - if (argc < 2) { - cerr << "No libraries specified.\n"; - exit(1); - } - - int return_status = 0; - - for (int i = 1; i < argc; i++) { - string param = argv[i]; - - if (param.length() > 3 && param.substr(param.length() - 3) == ".in") { - // If the filename ends in ".in", it's an interrogate database file, not - // a shared library--read it directly. - interrogate_request_database(param.c_str()); - - } else { - // Otherwise, assume it's a shared library, and try to load it. - Filename pathname = Filename::dso_filename(argv[i]); - cerr << "Loading " << pathname << "\n"; - -#ifdef _WIN32 - // test_interrogate always wants to show an error dialog. - SetErrorMode(0); -#endif - - void *dl = load_dso(DSearchPath(), pathname); - if (dl == nullptr) { - cerr << "Unable to load: " << load_dso_error() << "\n"; - return_status++; - } - } - } - - if (!quick_load) { - if (all_types) { - report_all_types(); - } - if (all_functions) { - report_all_functions(); - } - - if (!all_types && !all_functions) { - report_manifests(); - report_globals(); - report_global_types(); - report_global_functions(); - } - } - - return (return_status); -} diff --git a/dtool/src/test_interrogate/test_lib.cxx b/dtool/src/test_interrogate/test_lib.cxx deleted file mode 100644 index 89ccafccfc..0000000000 --- a/dtool/src/test_interrogate/test_lib.cxx +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file test_lib.cxx - * @author frang - * @date 2000-06-15 - */ - -#include "test_lib.h" - -int non_member1(float x, float y) { - return (int)(x + y); -} - -my_class1::my_class1(void) {} - -my_class1::my_class1(int) {} - -my_class1::~my_class1(void) {} - -float my_class1::method1(int x) { return (float)(x); } - -int my_class1::method2(float x) { return (int)(x); } - -int stupid_global; - -#include "dconfig.h" - -Configure(test_lib); - -ConfigureFn(test_lib) { - std::cerr << "In test_lib configure function!" << std::endl; -} - -ConfigureLibSym; diff --git a/dtool/src/test_interrogate/test_lib.h b/dtool/src/test_interrogate/test_lib.h deleted file mode 100644 index 9b316c941e..0000000000 --- a/dtool/src/test_interrogate/test_lib.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file test_lib.h - * @author frang - * @date 2000-06-15 - */ - -#ifndef __TEST_LIB_H__ -#define __TEST_LIB_H__ - -int non_member1(float x, float); - -class my_class1 { -public: - my_class1(void); - my_class1(int); - - float method1(int); - - int _member1; -private: - ~my_class1(void); - - int method2(float); - - int _member2; -}; - -#endif /* __TEST_LIB_H__ */