openssl use 1.1.1k , curl use static link
This commit is contained in:
parent
cfb451bd17
commit
5f4f7208b8
|
|
@ -95,9 +95,9 @@ set_target_properties(websockets PROPERTIES
|
|||
INTERFACE_INCLUDE_DIRECTORIES ${platform_spec_path}/include/libwebsockets
|
||||
)
|
||||
|
||||
add_library(curl SHARED IMPORTED GLOBAL)
|
||||
add_library(curl STATIC IMPORTED GLOBAL)
|
||||
set_target_properties(curl PROPERTIES
|
||||
IMPORTED_LOCATION ${linux_lib_dir}/curl/libcurl.so
|
||||
IMPORTED_LOCATION ${linux_lib_dir}/curl/libcurl.a
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${platform_spec_path}/include/curl
|
||||
)
|
||||
|
||||
|
|
@ -176,10 +176,9 @@ list(APPEND CC_EXTERNAL_LIBS
|
|||
jpeg
|
||||
png
|
||||
websockets
|
||||
crypto
|
||||
curl
|
||||
webp
|
||||
sdl2
|
||||
curl
|
||||
${optional_libs_name}
|
||||
${glslang_libs_name}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,577 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
||||
// Copyright (C) 2017 ARM Limited.
|
||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _BASICTYPES_INCLUDED_
|
||||
#define _BASICTYPES_INCLUDED_
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this.
|
||||
//
|
||||
enum TBasicType {
|
||||
EbtVoid,
|
||||
EbtFloat,
|
||||
EbtDouble,
|
||||
EbtFloat16,
|
||||
EbtInt8,
|
||||
EbtUint8,
|
||||
EbtInt16,
|
||||
EbtUint16,
|
||||
EbtInt,
|
||||
EbtUint,
|
||||
EbtInt64,
|
||||
EbtUint64,
|
||||
EbtBool,
|
||||
EbtAtomicUint,
|
||||
EbtSampler,
|
||||
EbtStruct,
|
||||
EbtBlock,
|
||||
EbtAccStruct,
|
||||
EbtReference,
|
||||
EbtRayQuery,
|
||||
|
||||
// HLSL types that live only temporarily.
|
||||
EbtString,
|
||||
|
||||
EbtNumTypes
|
||||
};
|
||||
|
||||
//
|
||||
// Storage qualifiers. Should align with different kinds of storage or
|
||||
// resource or GLSL storage qualifier. Expansion is deprecated.
|
||||
//
|
||||
// N.B.: You probably DON'T want to add anything here, but rather just add it
|
||||
// to the built-in variables. See the comment above TBuiltInVariable.
|
||||
//
|
||||
// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc.
|
||||
// DO NOT follow the design pattern of, say EvqInstanceId, etc.
|
||||
//
|
||||
enum TStorageQualifier {
|
||||
EvqTemporary, // For temporaries (within a function), read/write
|
||||
EvqGlobal, // For globals read/write
|
||||
EvqConst, // User-defined constant values, will be semantically constant and constant folded
|
||||
EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable)
|
||||
EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable)
|
||||
EvqUniform, // read only, shared with app
|
||||
EvqBuffer, // read/write, shared with app
|
||||
EvqShared, // compute shader's read/write 'shared' qualifier
|
||||
|
||||
EvqPayload,
|
||||
EvqPayloadIn,
|
||||
EvqHitAttr,
|
||||
EvqCallableData,
|
||||
EvqCallableDataIn,
|
||||
|
||||
// parameters
|
||||
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
|
||||
EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
|
||||
EvqInOut,
|
||||
EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics
|
||||
|
||||
// built-ins read by vertex shader
|
||||
EvqVertexId,
|
||||
EvqInstanceId,
|
||||
|
||||
// built-ins written by vertex shader
|
||||
EvqPosition,
|
||||
EvqPointSize,
|
||||
EvqClipVertex,
|
||||
|
||||
// built-ins read by fragment shader
|
||||
EvqFace,
|
||||
EvqFragCoord,
|
||||
EvqPointCoord,
|
||||
|
||||
// built-ins written by fragment shader
|
||||
EvqFragColor,
|
||||
EvqFragDepth,
|
||||
|
||||
// end of list
|
||||
EvqLast
|
||||
};
|
||||
|
||||
//
|
||||
// Subcategories of the TStorageQualifier, simply to give a direct mapping
|
||||
// between built-in variable names and an numerical value (the enum).
|
||||
//
|
||||
// For backward compatibility, there is some redundancy between the
|
||||
// TStorageQualifier and these. Existing members should both be maintained accurately.
|
||||
// However, any new built-in variable (and any existing non-redundant one)
|
||||
// must follow the pattern that the specific built-in is here, and only its
|
||||
// general qualifier is in TStorageQualifier.
|
||||
//
|
||||
// Something like gl_Position, which is sometimes 'in' and sometimes 'out'
|
||||
// shows up as two different built-in variables in a single stage, but
|
||||
// only has a single enum in TBuiltInVariable, so both the
|
||||
// TStorageQualifier and the TBuitinVariable are needed to distinguish
|
||||
// between them.
|
||||
//
|
||||
enum TBuiltInVariable {
|
||||
EbvNone,
|
||||
EbvNumWorkGroups,
|
||||
EbvWorkGroupSize,
|
||||
EbvWorkGroupId,
|
||||
EbvLocalInvocationId,
|
||||
EbvGlobalInvocationId,
|
||||
EbvLocalInvocationIndex,
|
||||
EbvNumSubgroups,
|
||||
EbvSubgroupID,
|
||||
EbvSubGroupSize,
|
||||
EbvSubGroupInvocation,
|
||||
EbvSubGroupEqMask,
|
||||
EbvSubGroupGeMask,
|
||||
EbvSubGroupGtMask,
|
||||
EbvSubGroupLeMask,
|
||||
EbvSubGroupLtMask,
|
||||
EbvSubgroupSize2,
|
||||
EbvSubgroupInvocation2,
|
||||
EbvSubgroupEqMask2,
|
||||
EbvSubgroupGeMask2,
|
||||
EbvSubgroupGtMask2,
|
||||
EbvSubgroupLeMask2,
|
||||
EbvSubgroupLtMask2,
|
||||
EbvVertexId,
|
||||
EbvInstanceId,
|
||||
EbvVertexIndex,
|
||||
EbvInstanceIndex,
|
||||
EbvBaseVertex,
|
||||
EbvBaseInstance,
|
||||
EbvDrawId,
|
||||
EbvPosition,
|
||||
EbvPointSize,
|
||||
EbvClipVertex,
|
||||
EbvClipDistance,
|
||||
EbvCullDistance,
|
||||
EbvNormal,
|
||||
EbvVertex,
|
||||
EbvMultiTexCoord0,
|
||||
EbvMultiTexCoord1,
|
||||
EbvMultiTexCoord2,
|
||||
EbvMultiTexCoord3,
|
||||
EbvMultiTexCoord4,
|
||||
EbvMultiTexCoord5,
|
||||
EbvMultiTexCoord6,
|
||||
EbvMultiTexCoord7,
|
||||
EbvFrontColor,
|
||||
EbvBackColor,
|
||||
EbvFrontSecondaryColor,
|
||||
EbvBackSecondaryColor,
|
||||
EbvTexCoord,
|
||||
EbvFogFragCoord,
|
||||
EbvInvocationId,
|
||||
EbvPrimitiveId,
|
||||
EbvLayer,
|
||||
EbvViewportIndex,
|
||||
EbvPatchVertices,
|
||||
EbvTessLevelOuter,
|
||||
EbvTessLevelInner,
|
||||
EbvBoundingBox,
|
||||
EbvTessCoord,
|
||||
EbvColor,
|
||||
EbvSecondaryColor,
|
||||
EbvFace,
|
||||
EbvFragCoord,
|
||||
EbvPointCoord,
|
||||
EbvFragColor,
|
||||
EbvFragData,
|
||||
EbvFragDepth,
|
||||
EbvFragStencilRef,
|
||||
EbvSampleId,
|
||||
EbvSamplePosition,
|
||||
EbvSampleMask,
|
||||
EbvHelperInvocation,
|
||||
|
||||
EbvBaryCoordNoPersp,
|
||||
EbvBaryCoordNoPerspCentroid,
|
||||
EbvBaryCoordNoPerspSample,
|
||||
EbvBaryCoordSmooth,
|
||||
EbvBaryCoordSmoothCentroid,
|
||||
EbvBaryCoordSmoothSample,
|
||||
EbvBaryCoordPullModel,
|
||||
|
||||
EbvViewIndex,
|
||||
EbvDeviceIndex,
|
||||
|
||||
EbvShadingRateKHR,
|
||||
EbvPrimitiveShadingRateKHR,
|
||||
|
||||
EbvFragSizeEXT,
|
||||
EbvFragInvocationCountEXT,
|
||||
|
||||
EbvSecondaryFragDataEXT,
|
||||
EbvSecondaryFragColorEXT,
|
||||
|
||||
EbvViewportMaskNV,
|
||||
EbvSecondaryPositionNV,
|
||||
EbvSecondaryViewportMaskNV,
|
||||
EbvPositionPerViewNV,
|
||||
EbvViewportMaskPerViewNV,
|
||||
EbvFragFullyCoveredNV,
|
||||
EbvFragmentSizeNV,
|
||||
EbvInvocationsPerPixelNV,
|
||||
// ray tracing
|
||||
EbvLaunchId,
|
||||
EbvLaunchSize,
|
||||
EbvInstanceCustomIndex,
|
||||
EbvGeometryIndex,
|
||||
EbvWorldRayOrigin,
|
||||
EbvWorldRayDirection,
|
||||
EbvObjectRayOrigin,
|
||||
EbvObjectRayDirection,
|
||||
EbvRayTmin,
|
||||
EbvRayTmax,
|
||||
EbvHitT,
|
||||
EbvHitKind,
|
||||
EbvObjectToWorld,
|
||||
EbvObjectToWorld3x4,
|
||||
EbvWorldToObject,
|
||||
EbvWorldToObject3x4,
|
||||
EbvIncomingRayFlags,
|
||||
// barycentrics
|
||||
EbvBaryCoordNV,
|
||||
EbvBaryCoordNoPerspNV,
|
||||
// mesh shaders
|
||||
EbvTaskCountNV,
|
||||
EbvPrimitiveCountNV,
|
||||
EbvPrimitiveIndicesNV,
|
||||
EbvClipDistancePerViewNV,
|
||||
EbvCullDistancePerViewNV,
|
||||
EbvLayerPerViewNV,
|
||||
EbvMeshViewCountNV,
|
||||
EbvMeshViewIndicesNV,
|
||||
|
||||
// sm builtins
|
||||
EbvWarpsPerSM,
|
||||
EbvSMCount,
|
||||
EbvWarpID,
|
||||
EbvSMID,
|
||||
|
||||
// HLSL built-ins that live only temporarily, until they get remapped
|
||||
// to one of the above.
|
||||
EbvFragDepthGreater,
|
||||
EbvFragDepthLesser,
|
||||
EbvGsOutputStream,
|
||||
EbvOutputPatch,
|
||||
EbvInputPatch,
|
||||
|
||||
// structbuffer types
|
||||
EbvAppendConsume, // no need to differentiate append and consume
|
||||
EbvRWStructuredBuffer,
|
||||
EbvStructuredBuffer,
|
||||
EbvByteAddressBuffer,
|
||||
EbvRWByteAddressBuffer,
|
||||
|
||||
EbvLast
|
||||
};
|
||||
|
||||
// In this enum, order matters; users can assume higher precision is a bigger value
|
||||
// and EpqNone is 0.
|
||||
enum TPrecisionQualifier {
|
||||
EpqNone = 0,
|
||||
EpqLow,
|
||||
EpqMedium,
|
||||
EpqHigh
|
||||
};
|
||||
|
||||
#ifdef GLSLANG_WEB
|
||||
__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; }
|
||||
__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; }
|
||||
#else
|
||||
// These will show up in error messages
|
||||
__inline const char* GetStorageQualifierString(TStorageQualifier q)
|
||||
{
|
||||
switch (q) {
|
||||
case EvqTemporary: return "temp"; break;
|
||||
case EvqGlobal: return "global"; break;
|
||||
case EvqConst: return "const"; break;
|
||||
case EvqConstReadOnly: return "const (read only)"; break;
|
||||
case EvqVaryingIn: return "in"; break;
|
||||
case EvqVaryingOut: return "out"; break;
|
||||
case EvqUniform: return "uniform"; break;
|
||||
case EvqBuffer: return "buffer"; break;
|
||||
case EvqShared: return "shared"; break;
|
||||
case EvqIn: return "in"; break;
|
||||
case EvqOut: return "out"; break;
|
||||
case EvqInOut: return "inout"; break;
|
||||
case EvqVertexId: return "gl_VertexId"; break;
|
||||
case EvqInstanceId: return "gl_InstanceId"; break;
|
||||
case EvqPosition: return "gl_Position"; break;
|
||||
case EvqPointSize: return "gl_PointSize"; break;
|
||||
case EvqClipVertex: return "gl_ClipVertex"; break;
|
||||
case EvqFace: return "gl_FrontFacing"; break;
|
||||
case EvqFragCoord: return "gl_FragCoord"; break;
|
||||
case EvqPointCoord: return "gl_PointCoord"; break;
|
||||
case EvqFragColor: return "fragColor"; break;
|
||||
case EvqFragDepth: return "gl_FragDepth"; break;
|
||||
case EvqPayload: return "rayPayloadNV"; break;
|
||||
case EvqPayloadIn: return "rayPayloadInNV"; break;
|
||||
case EvqHitAttr: return "hitAttributeNV"; break;
|
||||
case EvqCallableData: return "callableDataNV"; break;
|
||||
case EvqCallableDataIn: return "callableDataInNV"; break;
|
||||
default: return "unknown qualifier";
|
||||
}
|
||||
}
|
||||
|
||||
__inline const char* GetBuiltInVariableString(TBuiltInVariable v)
|
||||
{
|
||||
switch (v) {
|
||||
case EbvNone: return "";
|
||||
case EbvNumWorkGroups: return "NumWorkGroups";
|
||||
case EbvWorkGroupSize: return "WorkGroupSize";
|
||||
case EbvWorkGroupId: return "WorkGroupID";
|
||||
case EbvLocalInvocationId: return "LocalInvocationID";
|
||||
case EbvGlobalInvocationId: return "GlobalInvocationID";
|
||||
case EbvLocalInvocationIndex: return "LocalInvocationIndex";
|
||||
case EbvNumSubgroups: return "NumSubgroups";
|
||||
case EbvSubgroupID: return "SubgroupID";
|
||||
case EbvSubGroupSize: return "SubGroupSize";
|
||||
case EbvSubGroupInvocation: return "SubGroupInvocation";
|
||||
case EbvSubGroupEqMask: return "SubGroupEqMask";
|
||||
case EbvSubGroupGeMask: return "SubGroupGeMask";
|
||||
case EbvSubGroupGtMask: return "SubGroupGtMask";
|
||||
case EbvSubGroupLeMask: return "SubGroupLeMask";
|
||||
case EbvSubGroupLtMask: return "SubGroupLtMask";
|
||||
case EbvSubgroupSize2: return "SubgroupSize";
|
||||
case EbvSubgroupInvocation2: return "SubgroupInvocationID";
|
||||
case EbvSubgroupEqMask2: return "SubgroupEqMask";
|
||||
case EbvSubgroupGeMask2: return "SubgroupGeMask";
|
||||
case EbvSubgroupGtMask2: return "SubgroupGtMask";
|
||||
case EbvSubgroupLeMask2: return "SubgroupLeMask";
|
||||
case EbvSubgroupLtMask2: return "SubgroupLtMask";
|
||||
case EbvVertexId: return "VertexId";
|
||||
case EbvInstanceId: return "InstanceId";
|
||||
case EbvVertexIndex: return "VertexIndex";
|
||||
case EbvInstanceIndex: return "InstanceIndex";
|
||||
case EbvBaseVertex: return "BaseVertex";
|
||||
case EbvBaseInstance: return "BaseInstance";
|
||||
case EbvDrawId: return "DrawId";
|
||||
case EbvPosition: return "Position";
|
||||
case EbvPointSize: return "PointSize";
|
||||
case EbvClipVertex: return "ClipVertex";
|
||||
case EbvClipDistance: return "ClipDistance";
|
||||
case EbvCullDistance: return "CullDistance";
|
||||
case EbvNormal: return "Normal";
|
||||
case EbvVertex: return "Vertex";
|
||||
case EbvMultiTexCoord0: return "MultiTexCoord0";
|
||||
case EbvMultiTexCoord1: return "MultiTexCoord1";
|
||||
case EbvMultiTexCoord2: return "MultiTexCoord2";
|
||||
case EbvMultiTexCoord3: return "MultiTexCoord3";
|
||||
case EbvMultiTexCoord4: return "MultiTexCoord4";
|
||||
case EbvMultiTexCoord5: return "MultiTexCoord5";
|
||||
case EbvMultiTexCoord6: return "MultiTexCoord6";
|
||||
case EbvMultiTexCoord7: return "MultiTexCoord7";
|
||||
case EbvFrontColor: return "FrontColor";
|
||||
case EbvBackColor: return "BackColor";
|
||||
case EbvFrontSecondaryColor: return "FrontSecondaryColor";
|
||||
case EbvBackSecondaryColor: return "BackSecondaryColor";
|
||||
case EbvTexCoord: return "TexCoord";
|
||||
case EbvFogFragCoord: return "FogFragCoord";
|
||||
case EbvInvocationId: return "InvocationID";
|
||||
case EbvPrimitiveId: return "PrimitiveID";
|
||||
case EbvLayer: return "Layer";
|
||||
case EbvViewportIndex: return "ViewportIndex";
|
||||
case EbvPatchVertices: return "PatchVertices";
|
||||
case EbvTessLevelOuter: return "TessLevelOuter";
|
||||
case EbvTessLevelInner: return "TessLevelInner";
|
||||
case EbvBoundingBox: return "BoundingBox";
|
||||
case EbvTessCoord: return "TessCoord";
|
||||
case EbvColor: return "Color";
|
||||
case EbvSecondaryColor: return "SecondaryColor";
|
||||
case EbvFace: return "Face";
|
||||
case EbvFragCoord: return "FragCoord";
|
||||
case EbvPointCoord: return "PointCoord";
|
||||
case EbvFragColor: return "FragColor";
|
||||
case EbvFragData: return "FragData";
|
||||
case EbvFragDepth: return "FragDepth";
|
||||
case EbvFragStencilRef: return "FragStencilRef";
|
||||
case EbvSampleId: return "SampleId";
|
||||
case EbvSamplePosition: return "SamplePosition";
|
||||
case EbvSampleMask: return "SampleMaskIn";
|
||||
case EbvHelperInvocation: return "HelperInvocation";
|
||||
|
||||
case EbvBaryCoordNoPersp: return "BaryCoordNoPersp";
|
||||
case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid";
|
||||
case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample";
|
||||
case EbvBaryCoordSmooth: return "BaryCoordSmooth";
|
||||
case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid";
|
||||
case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample";
|
||||
case EbvBaryCoordPullModel: return "BaryCoordPullModel";
|
||||
|
||||
case EbvViewIndex: return "ViewIndex";
|
||||
case EbvDeviceIndex: return "DeviceIndex";
|
||||
|
||||
case EbvFragSizeEXT: return "FragSizeEXT";
|
||||
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
|
||||
|
||||
case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT";
|
||||
case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT";
|
||||
|
||||
case EbvViewportMaskNV: return "ViewportMaskNV";
|
||||
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
|
||||
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
|
||||
case EbvPositionPerViewNV: return "PositionPerViewNV";
|
||||
case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
|
||||
case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
|
||||
case EbvFragmentSizeNV: return "FragmentSizeNV";
|
||||
case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV";
|
||||
case EbvLaunchId: return "LaunchIdNV";
|
||||
case EbvLaunchSize: return "LaunchSizeNV";
|
||||
case EbvInstanceCustomIndex: return "InstanceCustomIndexNV";
|
||||
case EbvGeometryIndex: return "GeometryIndexEXT";
|
||||
case EbvWorldRayOrigin: return "WorldRayOriginNV";
|
||||
case EbvWorldRayDirection: return "WorldRayDirectionNV";
|
||||
case EbvObjectRayOrigin: return "ObjectRayOriginNV";
|
||||
case EbvObjectRayDirection: return "ObjectRayDirectionNV";
|
||||
case EbvRayTmin: return "ObjectRayTminNV";
|
||||
case EbvRayTmax: return "ObjectRayTmaxNV";
|
||||
case EbvHitT: return "HitTNV";
|
||||
case EbvHitKind: return "HitKindNV";
|
||||
case EbvIncomingRayFlags: return "IncomingRayFlagsNV";
|
||||
case EbvObjectToWorld: return "ObjectToWorldNV";
|
||||
case EbvWorldToObject: return "WorldToObjectNV";
|
||||
|
||||
case EbvBaryCoordNV: return "BaryCoordNV";
|
||||
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
|
||||
|
||||
case EbvTaskCountNV: return "TaskCountNV";
|
||||
case EbvPrimitiveCountNV: return "PrimitiveCountNV";
|
||||
case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV";
|
||||
case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV";
|
||||
case EbvCullDistancePerViewNV: return "CullDistancePerViewNV";
|
||||
case EbvLayerPerViewNV: return "LayerPerViewNV";
|
||||
case EbvMeshViewCountNV: return "MeshViewCountNV";
|
||||
case EbvMeshViewIndicesNV: return "MeshViewIndicesNV";
|
||||
|
||||
case EbvWarpsPerSM: return "WarpsPerSMNV";
|
||||
case EbvSMCount: return "SMCountNV";
|
||||
case EbvWarpID: return "WarpIDNV";
|
||||
case EbvSMID: return "SMIDNV";
|
||||
|
||||
case EbvShadingRateKHR: return "ShadingRateKHR";
|
||||
case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR";
|
||||
|
||||
default: return "unknown built-in variable";
|
||||
}
|
||||
}
|
||||
|
||||
__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p)
|
||||
{
|
||||
switch (p) {
|
||||
case EpqNone: return ""; break;
|
||||
case EpqLow: return "lowp"; break;
|
||||
case EpqMedium: return "mediump"; break;
|
||||
case EpqHigh: return "highp"; break;
|
||||
default: return "unknown precision qualifier";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__inline bool isTypeSignedInt(TBasicType type)
|
||||
{
|
||||
switch (type) {
|
||||
case EbtInt8:
|
||||
case EbtInt16:
|
||||
case EbtInt:
|
||||
case EbtInt64:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
__inline bool isTypeUnsignedInt(TBasicType type)
|
||||
{
|
||||
switch (type) {
|
||||
case EbtUint8:
|
||||
case EbtUint16:
|
||||
case EbtUint:
|
||||
case EbtUint64:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
__inline bool isTypeInt(TBasicType type)
|
||||
{
|
||||
return isTypeSignedInt(type) || isTypeUnsignedInt(type);
|
||||
}
|
||||
|
||||
__inline bool isTypeFloat(TBasicType type)
|
||||
{
|
||||
switch (type) {
|
||||
case EbtFloat:
|
||||
case EbtDouble:
|
||||
case EbtFloat16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
__inline int getTypeRank(TBasicType type)
|
||||
{
|
||||
int res = -1;
|
||||
switch(type) {
|
||||
case EbtInt8:
|
||||
case EbtUint8:
|
||||
res = 0;
|
||||
break;
|
||||
case EbtInt16:
|
||||
case EbtUint16:
|
||||
res = 1;
|
||||
break;
|
||||
case EbtInt:
|
||||
case EbtUint:
|
||||
res = 2;
|
||||
break;
|
||||
case EbtInt64:
|
||||
case EbtUint64:
|
||||
res = 3;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _BASICTYPES_INCLUDED_
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _COMMON_INCLUDED_
|
||||
#define _COMMON_INCLUDED_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
|
||||
#include <sstream>
|
||||
namespace std {
|
||||
template<typename T>
|
||||
std::string to_string(const T& val) {
|
||||
std::ostringstream os;
|
||||
os << val;
|
||||
return os.str();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API
|
||||
#include <basetsd.h>
|
||||
#ifndef snprintf
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
#define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args))
|
||||
#elif defined (solaris)
|
||||
#define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
|
||||
#include <sys/int_types.h>
|
||||
#define UINT_PTR uintptr_t
|
||||
#else
|
||||
#define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
|
||||
#include <stdint.h>
|
||||
#define UINT_PTR uintptr_t
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
#include <stdlib.h>
|
||||
inline long long int strtoll (const char* str, char** endptr, int base)
|
||||
{
|
||||
return _strtoi64(str, endptr, base);
|
||||
}
|
||||
inline unsigned long long int strtoull (const char* str, char** endptr, int base)
|
||||
{
|
||||
return _strtoui64(str, endptr, base);
|
||||
}
|
||||
inline long long int atoll (const char* str)
|
||||
{
|
||||
return strtoll(str, NULL, 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
/* windows only pragma */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4786) // Don't warn about too long identifiers
|
||||
#pragma warning(disable : 4514) // unused inline method
|
||||
#pragma warning(disable : 4201) // nameless union
|
||||
#endif
|
||||
|
||||
#include "PoolAlloc.h"
|
||||
|
||||
//
|
||||
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
|
||||
//
|
||||
#define POOL_ALLOCATOR_NEW_DELETE(A) \
|
||||
void* operator new(size_t s) { return (A).allocate(s); } \
|
||||
void* operator new(size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete(void*) { } \
|
||||
void operator delete(void *, void *) { } \
|
||||
void* operator new[](size_t s) { return (A).allocate(s); } \
|
||||
void* operator new[](size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete[](void*) { } \
|
||||
void operator delete[](void *, void *) { }
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// Pool version of string.
|
||||
//
|
||||
typedef pool_allocator<char> TStringAllocator;
|
||||
typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
// Repackage the std::hash for use by unordered map/set with a TString key.
|
||||
namespace std {
|
||||
|
||||
template<> struct hash<glslang::TString> {
|
||||
std::size_t operator()(const glslang::TString& s) const
|
||||
{
|
||||
const unsigned _FNV_offset_basis = 2166136261U;
|
||||
const unsigned _FNV_prime = 16777619U;
|
||||
unsigned _Val = _FNV_offset_basis;
|
||||
size_t _Count = s.size();
|
||||
const char* _First = s.c_str();
|
||||
for (size_t _Next = 0; _Next < _Count; ++_Next)
|
||||
{
|
||||
_Val ^= (unsigned)_First[_Next];
|
||||
_Val *= _FNV_prime;
|
||||
}
|
||||
|
||||
return _Val;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace glslang {
|
||||
|
||||
inline TString* NewPoolTString(const char* s)
|
||||
{
|
||||
void* memory = GetThreadPoolAllocator().allocate(sizeof(TString));
|
||||
return new(memory) TString(s);
|
||||
}
|
||||
|
||||
template<class T> inline T* NewPoolObject(T*)
|
||||
{
|
||||
return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
|
||||
}
|
||||
|
||||
template<class T> inline T* NewPoolObject(T, int instances)
|
||||
{
|
||||
return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances];
|
||||
}
|
||||
|
||||
//
|
||||
// Pool allocator versions of vectors, lists, and maps
|
||||
//
|
||||
template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
|
||||
TVector() : std::vector<T, pool_allocator<T> >() {}
|
||||
TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
|
||||
TVector(size_type i) : std::vector<T, pool_allocator<T> >(i) {}
|
||||
TVector(size_type i, const T& val) : std::vector<T, pool_allocator<T> >(i, val) {}
|
||||
};
|
||||
|
||||
template <class T> class TList : public std::list<T, pool_allocator<T> > {
|
||||
};
|
||||
|
||||
template <class K, class D, class CMP = std::less<K> >
|
||||
class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<K const, D> > > {
|
||||
};
|
||||
|
||||
template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_to<K> >
|
||||
class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
|
||||
};
|
||||
|
||||
//
|
||||
// Persistent string memory. Should only be used for strings that survive
|
||||
// across compiles/links.
|
||||
//
|
||||
typedef std::basic_string<char> TPersistString;
|
||||
|
||||
//
|
||||
// templatized min and max functions.
|
||||
//
|
||||
template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
|
||||
template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
|
||||
|
||||
//
|
||||
// Create a TString object from an integer.
|
||||
//
|
||||
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
|
||||
inline const TString String(const int i, const int base = 10)
|
||||
{
|
||||
char text[16]; // 32 bit ints are at most 10 digits in base 10
|
||||
_itoa_s(i, text, sizeof(text), base);
|
||||
return text;
|
||||
}
|
||||
#else
|
||||
inline const TString String(const int i, const int /*base*/ = 10)
|
||||
{
|
||||
char text[16]; // 32 bit ints are at most 10 digits in base 10
|
||||
|
||||
// we assume base 10 for all cases
|
||||
snprintf(text, sizeof(text), "%d", i);
|
||||
|
||||
return text;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct TSourceLoc {
|
||||
void init()
|
||||
{
|
||||
name = nullptr; string = 0; line = 0; column = 0;
|
||||
}
|
||||
void init(int stringNum) { init(); string = stringNum; }
|
||||
// Returns the name if it exists. Otherwise, returns the string number.
|
||||
std::string getStringNameOrNum(bool quoteStringName = true) const
|
||||
{
|
||||
if (name != nullptr) {
|
||||
TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
|
||||
std::string ret_str(qstr.c_str());
|
||||
return ret_str;
|
||||
}
|
||||
return std::to_string((long long)string);
|
||||
}
|
||||
const char* getFilename() const
|
||||
{
|
||||
if (name == nullptr)
|
||||
return nullptr;
|
||||
return name->c_str();
|
||||
}
|
||||
const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); }
|
||||
TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr
|
||||
int string;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
class TPragmaTable : public TMap<TString, TString> {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
};
|
||||
|
||||
const int MaxTokenLength = 1024;
|
||||
|
||||
template <class T> bool IsPow2(T powerOf2)
|
||||
{
|
||||
if (powerOf2 <= 0)
|
||||
return false;
|
||||
|
||||
return (powerOf2 & (powerOf2 - 1)) == 0;
|
||||
}
|
||||
|
||||
// Round number up to a multiple of the given powerOf2, which is not
|
||||
// a power, just a number that must be a power of 2.
|
||||
template <class T> void RoundToPow2(T& number, int powerOf2)
|
||||
{
|
||||
assert(IsPow2(powerOf2));
|
||||
number = (number + powerOf2 - 1) & ~(powerOf2 - 1);
|
||||
}
|
||||
|
||||
template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
|
||||
{
|
||||
assert(IsPow2(powerOf2));
|
||||
return ! (number & (powerOf2 - 1));
|
||||
}
|
||||
|
||||
// Returns log2 of an integer power of 2.
|
||||
// T should be integral.
|
||||
template <class T> int IntLog2(T n)
|
||||
{
|
||||
assert(IsPow2(n));
|
||||
int result = 0;
|
||||
while ((T(1) << result) != n) {
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _COMMON_INCLUDED_
|
||||
|
|
@ -0,0 +1,974 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2013 LunarG, Inc.
|
||||
// Copyright (C) 2017 ARM Limited.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _CONSTANT_UNION_INCLUDED_
|
||||
#define _CONSTANT_UNION_INCLUDED_
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include "../Include/BaseTypes.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TConstUnion {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
TConstUnion() : iConst(0), type(EbtInt) { }
|
||||
|
||||
void setI8Const(signed char i)
|
||||
{
|
||||
i8Const = i;
|
||||
type = EbtInt8;
|
||||
}
|
||||
|
||||
void setU8Const(unsigned char u)
|
||||
{
|
||||
u8Const = u;
|
||||
type = EbtUint8;
|
||||
}
|
||||
|
||||
void setI16Const(signed short i)
|
||||
{
|
||||
i16Const = i;
|
||||
type = EbtInt16;
|
||||
}
|
||||
|
||||
void setU16Const(unsigned short u)
|
||||
{
|
||||
u16Const = u;
|
||||
type = EbtUint16;
|
||||
}
|
||||
|
||||
void setIConst(int i)
|
||||
{
|
||||
iConst = i;
|
||||
type = EbtInt;
|
||||
}
|
||||
|
||||
void setUConst(unsigned int u)
|
||||
{
|
||||
uConst = u;
|
||||
type = EbtUint;
|
||||
}
|
||||
|
||||
void setI64Const(long long i64)
|
||||
{
|
||||
i64Const = i64;
|
||||
type = EbtInt64;
|
||||
}
|
||||
|
||||
void setU64Const(unsigned long long u64)
|
||||
{
|
||||
u64Const = u64;
|
||||
type = EbtUint64;
|
||||
}
|
||||
|
||||
void setDConst(double d)
|
||||
{
|
||||
dConst = d;
|
||||
type = EbtDouble;
|
||||
}
|
||||
|
||||
void setBConst(bool b)
|
||||
{
|
||||
bConst = b;
|
||||
type = EbtBool;
|
||||
}
|
||||
|
||||
void setSConst(const TString* s)
|
||||
{
|
||||
sConst = s;
|
||||
type = EbtString;
|
||||
}
|
||||
|
||||
signed char getI8Const() const { return i8Const; }
|
||||
unsigned char getU8Const() const { return u8Const; }
|
||||
signed short getI16Const() const { return i16Const; }
|
||||
unsigned short getU16Const() const { return u16Const; }
|
||||
int getIConst() const { return iConst; }
|
||||
unsigned int getUConst() const { return uConst; }
|
||||
long long getI64Const() const { return i64Const; }
|
||||
unsigned long long getU64Const() const { return u64Const; }
|
||||
double getDConst() const { return dConst; }
|
||||
bool getBConst() const { return bConst; }
|
||||
const TString* getSConst() const { return sConst; }
|
||||
|
||||
bool operator==(const signed char i) const
|
||||
{
|
||||
if (i == i8Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const unsigned char u) const
|
||||
{
|
||||
if (u == u8Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const signed short i) const
|
||||
{
|
||||
if (i == i16Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const unsigned short u) const
|
||||
{
|
||||
if (u == u16Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const int i) const
|
||||
{
|
||||
if (i == iConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const unsigned int u) const
|
||||
{
|
||||
if (u == uConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const long long i64) const
|
||||
{
|
||||
if (i64 == i64Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const unsigned long long u64) const
|
||||
{
|
||||
if (u64 == u64Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const double d) const
|
||||
{
|
||||
if (d == dConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const bool b) const
|
||||
{
|
||||
if (b == bConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const TConstUnion& constant) const
|
||||
{
|
||||
if (constant.type != type)
|
||||
return false;
|
||||
|
||||
switch (type) {
|
||||
case EbtInt:
|
||||
if (constant.iConst == iConst)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtUint:
|
||||
if (constant.uConst == uConst)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtBool:
|
||||
if (constant.bConst == bConst)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtDouble:
|
||||
if (constant.dConst == dConst)
|
||||
return true;
|
||||
|
||||
break;
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt16:
|
||||
if (constant.i16Const == i16Const)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtUint16:
|
||||
if (constant.u16Const == u16Const)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtInt8:
|
||||
if (constant.i8Const == i8Const)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtUint8:
|
||||
if (constant.u8Const == u8Const)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtInt64:
|
||||
if (constant.i64Const == i64Const)
|
||||
return true;
|
||||
|
||||
break;
|
||||
case EbtUint64:
|
||||
if (constant.u64Const == u64Const)
|
||||
return true;
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const signed char i) const
|
||||
{
|
||||
return !operator==(i);
|
||||
}
|
||||
|
||||
bool operator!=(const unsigned char u) const
|
||||
{
|
||||
return !operator==(u);
|
||||
}
|
||||
|
||||
bool operator!=(const signed short i) const
|
||||
{
|
||||
return !operator==(i);
|
||||
}
|
||||
|
||||
bool operator!=(const unsigned short u) const
|
||||
{
|
||||
return !operator==(u);
|
||||
}
|
||||
|
||||
bool operator!=(const int i) const
|
||||
{
|
||||
return !operator==(i);
|
||||
}
|
||||
|
||||
bool operator!=(const unsigned int u) const
|
||||
{
|
||||
return !operator==(u);
|
||||
}
|
||||
|
||||
bool operator!=(const long long i) const
|
||||
{
|
||||
return !operator==(i);
|
||||
}
|
||||
|
||||
bool operator!=(const unsigned long long u) const
|
||||
{
|
||||
return !operator==(u);
|
||||
}
|
||||
|
||||
bool operator!=(const float f) const
|
||||
{
|
||||
return !operator==(f);
|
||||
}
|
||||
|
||||
bool operator!=(const bool b) const
|
||||
{
|
||||
return !operator==(b);
|
||||
}
|
||||
|
||||
bool operator!=(const TConstUnion& constant) const
|
||||
{
|
||||
return !operator==(constant);
|
||||
}
|
||||
|
||||
bool operator>(const TConstUnion& constant) const
|
||||
{
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt:
|
||||
if (iConst > constant.iConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint:
|
||||
if (uConst > constant.uConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtDouble:
|
||||
if (dConst > constant.dConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8:
|
||||
if (i8Const > constant.i8Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint8:
|
||||
if (u8Const > constant.u8Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtInt16:
|
||||
if (i16Const > constant.i16Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint16:
|
||||
if (u16Const > constant.u16Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtInt64:
|
||||
if (i64Const > constant.i64Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint64:
|
||||
if (u64Const > constant.u64Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#endif
|
||||
default:
|
||||
assert(false && "Default missing");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const TConstUnion& constant) const
|
||||
{
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8:
|
||||
if (i8Const < constant.i8Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint8:
|
||||
if (u8Const < constant.u8Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtInt16:
|
||||
if (i16Const < constant.i16Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint16:
|
||||
if (u16Const < constant.u16Const)
|
||||
return true;
|
||||
return false;
|
||||
case EbtInt64:
|
||||
if (i64Const < constant.i64Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint64:
|
||||
if (u64Const < constant.u64Const)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#endif
|
||||
case EbtDouble:
|
||||
if (dConst < constant.dConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtInt:
|
||||
if (iConst < constant.iConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
case EbtUint:
|
||||
if (uConst < constant.uConst)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
default:
|
||||
assert(false && "Default missing");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TConstUnion operator+(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst + constant.uConst); break;
|
||||
case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator-(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst - constant.uConst); break;
|
||||
case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator*(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst * constant.uConst); break;
|
||||
case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator%(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst % constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break;
|
||||
case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator>>(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
switch (type) {
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break;
|
||||
case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break;
|
||||
case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint8:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break;
|
||||
case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break;
|
||||
case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtInt16:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break;
|
||||
case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break;
|
||||
case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint16:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break;
|
||||
case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break;
|
||||
case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case EbtInt:
|
||||
switch (constant.type) {
|
||||
case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint:
|
||||
switch (constant.type) {
|
||||
case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt64:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break;
|
||||
case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint64:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break;
|
||||
case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break;
|
||||
case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break;
|
||||
case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator<<(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
switch (type) {
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break;
|
||||
case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break;
|
||||
case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break;
|
||||
case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint8:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break;
|
||||
case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break;
|
||||
case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break;
|
||||
case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtInt16:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break;
|
||||
case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break;
|
||||
case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break;
|
||||
case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint16:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break;
|
||||
case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break;
|
||||
case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break;
|
||||
case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtInt64:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break;
|
||||
case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break;
|
||||
case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint64:
|
||||
switch (constant.type) {
|
||||
case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break;
|
||||
case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break;
|
||||
case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break;
|
||||
case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case EbtInt:
|
||||
switch (constant.type) {
|
||||
case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
|
||||
case EbtUint: returnValue.setIConst(iConst << constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
case EbtUint:
|
||||
switch (constant.type) {
|
||||
case EbtInt: returnValue.setUConst(uConst << constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst << constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator&(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst & constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator|(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst | constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator^(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
|
||||
case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator~() const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(~iConst); break;
|
||||
case EbtUint: returnValue.setUConst(~uConst); break;
|
||||
#ifndef GLSLANG_WEB
|
||||
case EbtInt8: returnValue.setI8Const(~i8Const); break;
|
||||
case EbtUint8: returnValue.setU8Const(~u8Const); break;
|
||||
case EbtInt16: returnValue.setI16Const(~i16Const); break;
|
||||
case EbtUint16: returnValue.setU16Const(~u16Const); break;
|
||||
case EbtInt64: returnValue.setI64Const(~i64Const); break;
|
||||
case EbtUint64: returnValue.setU64Const(~u64Const); break;
|
||||
#endif
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator&&(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TConstUnion operator||(const TConstUnion& constant) const
|
||||
{
|
||||
TConstUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
|
||||
default: assert(false && "Default missing");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
TBasicType getType() const { return type; }
|
||||
|
||||
private:
|
||||
union {
|
||||
signed char i8Const; // used for i8vec, scalar int8s
|
||||
unsigned char u8Const; // used for u8vec, scalar uint8s
|
||||
signed short i16Const; // used for i16vec, scalar int16s
|
||||
unsigned short u16Const; // used for u16vec, scalar uint16s
|
||||
int iConst; // used for ivec, scalar ints
|
||||
unsigned int uConst; // used for uvec, scalar uints
|
||||
long long i64Const; // used for i64vec, scalar int64s
|
||||
unsigned long long u64Const; // used for u64vec, scalar uint64s
|
||||
bool bConst; // used for bvec, scalar bools
|
||||
double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles
|
||||
const TString* sConst; // string constant
|
||||
};
|
||||
|
||||
TBasicType type;
|
||||
};
|
||||
|
||||
// Encapsulate having a pointer to an array of TConstUnion,
|
||||
// which only needs to be allocated if its size is going to be
|
||||
// bigger than 0.
|
||||
//
|
||||
// One convenience is being able to use [] to go inside the array, instead
|
||||
// of C++ assuming it as an array of pointers to vectors.
|
||||
//
|
||||
// General usage is that the size is known up front, and it is
|
||||
// created once with the proper size.
|
||||
//
|
||||
class TConstUnionArray {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
TConstUnionArray() : unionArray(nullptr) { }
|
||||
virtual ~TConstUnionArray() { }
|
||||
|
||||
explicit TConstUnionArray(int size)
|
||||
{
|
||||
if (size == 0)
|
||||
unionArray = nullptr;
|
||||
else
|
||||
unionArray = new TConstUnionVector(size);
|
||||
}
|
||||
TConstUnionArray(const TConstUnionArray& a) = default;
|
||||
TConstUnionArray(const TConstUnionArray& a, int start, int size)
|
||||
{
|
||||
unionArray = new TConstUnionVector(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
(*unionArray)[i] = a[start + i];
|
||||
}
|
||||
|
||||
// Use this constructor for a smear operation
|
||||
TConstUnionArray(int size, const TConstUnion& val)
|
||||
{
|
||||
unionArray = new TConstUnionVector(size, val);
|
||||
}
|
||||
|
||||
int size() const { return unionArray ? (int)unionArray->size() : 0; }
|
||||
TConstUnion& operator[](size_t index) { return (*unionArray)[index]; }
|
||||
const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; }
|
||||
bool operator==(const TConstUnionArray& rhs) const
|
||||
{
|
||||
// this includes the case that both are unallocated
|
||||
if (unionArray == rhs.unionArray)
|
||||
return true;
|
||||
|
||||
if (! unionArray || ! rhs.unionArray)
|
||||
return false;
|
||||
|
||||
return *unionArray == *rhs.unionArray;
|
||||
}
|
||||
bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); }
|
||||
|
||||
double dot(const TConstUnionArray& rhs)
|
||||
{
|
||||
assert(rhs.unionArray->size() == unionArray->size());
|
||||
double sum = 0.0;
|
||||
|
||||
for (size_t comp = 0; comp < unionArray->size(); ++comp)
|
||||
sum += (*this)[comp].getDConst() * rhs[comp].getDConst();
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool empty() const { return unionArray == nullptr; }
|
||||
|
||||
protected:
|
||||
typedef TVector<TConstUnion> TConstUnionVector;
|
||||
TConstUnionVector* unionArray;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _CONSTANT_UNION_INCLUDED_
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _INFOSINK_INCLUDED_
|
||||
#define _INFOSINK_INCLUDED_
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// TPrefixType is used to centralize how info log messages start.
|
||||
// See below.
|
||||
//
|
||||
enum TPrefixType {
|
||||
EPrefixNone,
|
||||
EPrefixWarning,
|
||||
EPrefixError,
|
||||
EPrefixInternalError,
|
||||
EPrefixUnimplemented,
|
||||
EPrefixNote
|
||||
};
|
||||
|
||||
enum TOutputStream {
|
||||
ENull = 0,
|
||||
EDebugger = 0x01,
|
||||
EStdOut = 0x02,
|
||||
EString = 0x04,
|
||||
};
|
||||
//
|
||||
// Encapsulate info logs for all objects that have them.
|
||||
//
|
||||
// The methods are a general set of tools for getting a variety of
|
||||
// messages and types inserted into the log.
|
||||
//
|
||||
class TInfoSinkBase {
|
||||
public:
|
||||
TInfoSinkBase() : outputStream(4) {}
|
||||
void erase() { sink.erase(); }
|
||||
TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
|
||||
TInfoSinkBase& operator<<(char c) { append(1, c); return *this; }
|
||||
TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
|
||||
TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
|
||||
TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; }
|
||||
TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size];
|
||||
snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n);
|
||||
append(buf);
|
||||
return *this; }
|
||||
TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; }
|
||||
TInfoSinkBase& operator+(const TString& t) { append(t); return *this; }
|
||||
TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; }
|
||||
TInfoSinkBase& operator+(const char* s) { append(s); return *this; }
|
||||
const char* c_str() const { return sink.c_str(); }
|
||||
void prefix(TPrefixType message) {
|
||||
switch(message) {
|
||||
case EPrefixNone: break;
|
||||
case EPrefixWarning: append("WARNING: "); break;
|
||||
case EPrefixError: append("ERROR: "); break;
|
||||
case EPrefixInternalError: append("INTERNAL ERROR: "); break;
|
||||
case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
|
||||
case EPrefixNote: append("NOTE: "); break;
|
||||
default: append("UNKNOWN ERROR: "); break;
|
||||
}
|
||||
}
|
||||
void location(const TSourceLoc& loc) {
|
||||
const int maxSize = 24;
|
||||
char locText[maxSize];
|
||||
snprintf(locText, maxSize, ":%d", loc.line);
|
||||
append(loc.getStringNameOrNum(false).c_str());
|
||||
append(locText);
|
||||
append(": ");
|
||||
}
|
||||
void message(TPrefixType message, const char* s) {
|
||||
prefix(message);
|
||||
append(s);
|
||||
append("\n");
|
||||
}
|
||||
void message(TPrefixType message, const char* s, const TSourceLoc& loc) {
|
||||
prefix(message);
|
||||
location(loc);
|
||||
append(s);
|
||||
append("\n");
|
||||
}
|
||||
|
||||
void setOutputStream(int output = 4)
|
||||
{
|
||||
outputStream = output;
|
||||
}
|
||||
|
||||
protected:
|
||||
void append(const char* s);
|
||||
|
||||
void append(int count, char c);
|
||||
void append(const TPersistString& t);
|
||||
void append(const TString& t);
|
||||
|
||||
void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
|
||||
sink.reserve(sink.capacity() + sink.capacity() / 2); }
|
||||
void appendToStream(const char* s);
|
||||
TPersistString sink;
|
||||
int outputStream;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
class TInfoSink {
|
||||
public:
|
||||
glslang::TInfoSinkBase info;
|
||||
glslang::TInfoSinkBase debug;
|
||||
};
|
||||
|
||||
#endif // _INFOSINK_INCLUDED_
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef __INITIALIZE_GLOBALS_INCLUDED_
|
||||
#define __INITIALIZE_GLOBALS_INCLUDED_
|
||||
|
||||
namespace glslang {
|
||||
|
||||
bool InitializePoolIndex();
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // __INITIALIZE_GLOBALS_INCLUDED_
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _POOLALLOC_INCLUDED_
|
||||
#define _POOLALLOC_INCLUDED_
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define GUARD_BLOCKS // define to enable guard block sanity checking
|
||||
#endif
|
||||
|
||||
//
|
||||
// This header defines an allocator that can be used to efficiently
|
||||
// allocate a large number of small requests for heap memory, with the
|
||||
// intention that they are not individually deallocated, but rather
|
||||
// collectively deallocated at one time.
|
||||
//
|
||||
// This simultaneously
|
||||
//
|
||||
// * Makes each individual allocation much more efficient; the
|
||||
// typical allocation is trivial.
|
||||
// * Completely avoids the cost of doing individual deallocation.
|
||||
// * Saves the trouble of tracking down and plugging a large class of leaks.
|
||||
//
|
||||
// Individual classes can use this allocator by supplying their own
|
||||
// new and delete methods.
|
||||
//
|
||||
// STL containers can use this allocator by using the pool_allocator
|
||||
// class as the allocator (second) template argument.
|
||||
//
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// If we are using guard blocks, we must track each individual
|
||||
// allocation. If we aren't using guard blocks, these
|
||||
// never get instantiated, so won't have any impact.
|
||||
//
|
||||
|
||||
class TAllocation {
|
||||
public:
|
||||
TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
|
||||
size(size), mem(mem), prevAlloc(prev) {
|
||||
// Allocations are bracketed:
|
||||
// [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
|
||||
// This would be cleaner with if (guardBlockSize)..., but that
|
||||
// makes the compiler print warnings about 0 length memsets,
|
||||
// even with the if() protecting them.
|
||||
# ifdef GUARD_BLOCKS
|
||||
memset(preGuard(), guardBlockBeginVal, guardBlockSize);
|
||||
memset(data(), userDataFill, size);
|
||||
memset(postGuard(), guardBlockEndVal, guardBlockSize);
|
||||
# endif
|
||||
}
|
||||
|
||||
void check() const {
|
||||
checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
|
||||
checkGuardBlock(postGuard(), guardBlockEndVal, "after");
|
||||
}
|
||||
|
||||
void checkAllocList() const;
|
||||
|
||||
// Return total size needed to accommodate user buffer of 'size',
|
||||
// plus our tracking data.
|
||||
inline static size_t allocationSize(size_t size) {
|
||||
return size + 2 * guardBlockSize + headerSize();
|
||||
}
|
||||
|
||||
// Offset from surrounding buffer to get to user data buffer.
|
||||
inline static unsigned char* offsetAllocation(unsigned char* m) {
|
||||
return m + guardBlockSize + headerSize();
|
||||
}
|
||||
|
||||
private:
|
||||
void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
|
||||
|
||||
// Find offsets to pre and post guard blocks, and user data buffer
|
||||
unsigned char* preGuard() const { return mem + headerSize(); }
|
||||
unsigned char* data() const { return preGuard() + guardBlockSize; }
|
||||
unsigned char* postGuard() const { return data() + size; }
|
||||
|
||||
size_t size; // size of the user data area
|
||||
unsigned char* mem; // beginning of our allocation (pts to header)
|
||||
TAllocation* prevAlloc; // prior allocation in the chain
|
||||
|
||||
const static unsigned char guardBlockBeginVal;
|
||||
const static unsigned char guardBlockEndVal;
|
||||
const static unsigned char userDataFill;
|
||||
|
||||
const static size_t guardBlockSize;
|
||||
# ifdef GUARD_BLOCKS
|
||||
inline static size_t headerSize() { return sizeof(TAllocation); }
|
||||
# else
|
||||
inline static size_t headerSize() { return 0; }
|
||||
# endif
|
||||
};
|
||||
|
||||
//
|
||||
// There are several stacks. One is to track the pushing and popping
|
||||
// of the user, and not yet implemented. The others are simply a
|
||||
// repositories of free pages or used pages.
|
||||
//
|
||||
// Page stacks are linked together with a simple header at the beginning
|
||||
// of each allocation obtained from the underlying OS. Multi-page allocations
|
||||
// are returned to the OS. Individual page allocations are kept for future
|
||||
// re-use.
|
||||
//
|
||||
// The "page size" used is not, nor must it match, the underlying OS
|
||||
// page size. But, having it be about that size or equal to a set of
|
||||
// pages is likely most optimal.
|
||||
//
|
||||
class TPoolAllocator {
|
||||
public:
|
||||
TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
|
||||
|
||||
//
|
||||
// Don't call the destructor just to free up the memory, call pop()
|
||||
//
|
||||
~TPoolAllocator();
|
||||
|
||||
//
|
||||
// Call push() to establish a new place to pop memory too. Does not
|
||||
// have to be called to get things started.
|
||||
//
|
||||
void push();
|
||||
|
||||
//
|
||||
// Call pop() to free all memory allocated since the last call to push(),
|
||||
// or if no last call to push, frees all memory since first allocation.
|
||||
//
|
||||
void pop();
|
||||
|
||||
//
|
||||
// Call popAll() to free all memory allocated.
|
||||
//
|
||||
void popAll();
|
||||
|
||||
//
|
||||
// Call allocate() to actually acquire memory. Returns 0 if no memory
|
||||
// available, otherwise a properly aligned pointer to 'numBytes' of memory.
|
||||
//
|
||||
void* allocate(size_t numBytes);
|
||||
|
||||
//
|
||||
// There is no deallocate. The point of this class is that
|
||||
// deallocation can be skipped by the user of it, as the model
|
||||
// of use is to simultaneously deallocate everything at once
|
||||
// by calling pop(), and to not have to solve memory leak problems.
|
||||
//
|
||||
|
||||
protected:
|
||||
friend struct tHeader;
|
||||
|
||||
struct tHeader {
|
||||
tHeader(tHeader* nextPage, size_t pageCount) :
|
||||
#ifdef GUARD_BLOCKS
|
||||
lastAllocation(0),
|
||||
#endif
|
||||
nextPage(nextPage), pageCount(pageCount) { }
|
||||
|
||||
~tHeader() {
|
||||
#ifdef GUARD_BLOCKS
|
||||
if (lastAllocation)
|
||||
lastAllocation->checkAllocList();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef GUARD_BLOCKS
|
||||
TAllocation* lastAllocation;
|
||||
#endif
|
||||
tHeader* nextPage;
|
||||
size_t pageCount;
|
||||
};
|
||||
|
||||
struct tAllocState {
|
||||
size_t offset;
|
||||
tHeader* page;
|
||||
};
|
||||
typedef std::vector<tAllocState> tAllocStack;
|
||||
|
||||
// Track allocations if and only if we're using guard blocks
|
||||
#ifndef GUARD_BLOCKS
|
||||
void* initializeAllocation(tHeader*, unsigned char* memory, size_t) {
|
||||
#else
|
||||
void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
|
||||
new(memory) TAllocation(numBytes, memory, block->lastAllocation);
|
||||
block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
|
||||
#endif
|
||||
|
||||
// This is optimized entirely away if GUARD_BLOCKS is not defined.
|
||||
return TAllocation::offsetAllocation(memory);
|
||||
}
|
||||
|
||||
size_t pageSize; // granularity of allocation from the OS
|
||||
size_t alignment; // all returned allocations will be aligned at
|
||||
// this granularity, which will be a power of 2
|
||||
size_t alignmentMask;
|
||||
size_t headerSkip; // amount of memory to skip to make room for the
|
||||
// header (basically, size of header, rounded
|
||||
// up to make it aligned
|
||||
size_t currentPageOffset; // next offset in top of inUseList to allocate from
|
||||
tHeader* freeList; // list of popped memory
|
||||
tHeader* inUseList; // list of all memory currently being used
|
||||
tAllocStack stack; // stack of where to allocate from, to partition pool
|
||||
|
||||
int numCalls; // just an interesting statistic
|
||||
size_t totalBytes; // just an interesting statistic
|
||||
private:
|
||||
TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator
|
||||
TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor
|
||||
};
|
||||
|
||||
//
|
||||
// There could potentially be many pools with pops happening at
|
||||
// different times. But a simple use is to have a global pop
|
||||
// with everyone using the same global allocator.
|
||||
//
|
||||
extern TPoolAllocator& GetThreadPoolAllocator();
|
||||
void SetThreadPoolAllocator(TPoolAllocator* poolAllocator);
|
||||
|
||||
//
|
||||
// This STL compatible allocator is intended to be used as the allocator
|
||||
// parameter to templatized STL containers, like vector and map.
|
||||
//
|
||||
// It will use the pools for allocation, and not
|
||||
// do any deallocation, but will still do destruction.
|
||||
//
|
||||
template<class T>
|
||||
class pool_allocator {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
template<class Other>
|
||||
struct rebind {
|
||||
typedef pool_allocator<Other> other;
|
||||
};
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) const { return &x; }
|
||||
|
||||
pool_allocator() : allocator(GetThreadPoolAllocator()) { }
|
||||
pool_allocator(TPoolAllocator& a) : allocator(a) { }
|
||||
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
|
||||
|
||||
template<class Other>
|
||||
pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
|
||||
|
||||
pointer allocate(size_type n) {
|
||||
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
|
||||
pointer allocate(size_type n, const void*) {
|
||||
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
|
||||
|
||||
void deallocate(void*, size_type) { }
|
||||
void deallocate(pointer, size_type) { }
|
||||
|
||||
pointer _Charalloc(size_t n) {
|
||||
return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
|
||||
|
||||
void construct(pointer p, const T& val) { new ((void *)p) T(val); }
|
||||
void destroy(pointer p) { p->T::~T(); }
|
||||
|
||||
bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
|
||||
bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
|
||||
|
||||
size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
|
||||
size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
|
||||
|
||||
TPoolAllocator& getAllocator() const { return allocator; }
|
||||
|
||||
protected:
|
||||
pool_allocator& operator=(const pool_allocator&) { return *this; }
|
||||
TPoolAllocator& allocator;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _POOLALLOC_INCLUDED_
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2013 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _RESOURCE_LIMITS_INCLUDED_
|
||||
#define _RESOURCE_LIMITS_INCLUDED_
|
||||
|
||||
struct TLimits {
|
||||
bool nonInductiveForLoops;
|
||||
bool whileLoops;
|
||||
bool doWhileLoops;
|
||||
bool generalUniformIndexing;
|
||||
bool generalAttributeMatrixVectorIndexing;
|
||||
bool generalVaryingIndexing;
|
||||
bool generalSamplerIndexing;
|
||||
bool generalVariableIndexing;
|
||||
bool generalConstantMatrixVectorIndexing;
|
||||
};
|
||||
|
||||
struct TBuiltInResource {
|
||||
int maxLights;
|
||||
int maxClipPlanes;
|
||||
int maxTextureUnits;
|
||||
int maxTextureCoords;
|
||||
int maxVertexAttribs;
|
||||
int maxVertexUniformComponents;
|
||||
int maxVaryingFloats;
|
||||
int maxVertexTextureImageUnits;
|
||||
int maxCombinedTextureImageUnits;
|
||||
int maxTextureImageUnits;
|
||||
int maxFragmentUniformComponents;
|
||||
int maxDrawBuffers;
|
||||
int maxVertexUniformVectors;
|
||||
int maxVaryingVectors;
|
||||
int maxFragmentUniformVectors;
|
||||
int maxVertexOutputVectors;
|
||||
int maxFragmentInputVectors;
|
||||
int minProgramTexelOffset;
|
||||
int maxProgramTexelOffset;
|
||||
int maxClipDistances;
|
||||
int maxComputeWorkGroupCountX;
|
||||
int maxComputeWorkGroupCountY;
|
||||
int maxComputeWorkGroupCountZ;
|
||||
int maxComputeWorkGroupSizeX;
|
||||
int maxComputeWorkGroupSizeY;
|
||||
int maxComputeWorkGroupSizeZ;
|
||||
int maxComputeUniformComponents;
|
||||
int maxComputeTextureImageUnits;
|
||||
int maxComputeImageUniforms;
|
||||
int maxComputeAtomicCounters;
|
||||
int maxComputeAtomicCounterBuffers;
|
||||
int maxVaryingComponents;
|
||||
int maxVertexOutputComponents;
|
||||
int maxGeometryInputComponents;
|
||||
int maxGeometryOutputComponents;
|
||||
int maxFragmentInputComponents;
|
||||
int maxImageUnits;
|
||||
int maxCombinedImageUnitsAndFragmentOutputs;
|
||||
int maxCombinedShaderOutputResources;
|
||||
int maxImageSamples;
|
||||
int maxVertexImageUniforms;
|
||||
int maxTessControlImageUniforms;
|
||||
int maxTessEvaluationImageUniforms;
|
||||
int maxGeometryImageUniforms;
|
||||
int maxFragmentImageUniforms;
|
||||
int maxCombinedImageUniforms;
|
||||
int maxGeometryTextureImageUnits;
|
||||
int maxGeometryOutputVertices;
|
||||
int maxGeometryTotalOutputComponents;
|
||||
int maxGeometryUniformComponents;
|
||||
int maxGeometryVaryingComponents;
|
||||
int maxTessControlInputComponents;
|
||||
int maxTessControlOutputComponents;
|
||||
int maxTessControlTextureImageUnits;
|
||||
int maxTessControlUniformComponents;
|
||||
int maxTessControlTotalOutputComponents;
|
||||
int maxTessEvaluationInputComponents;
|
||||
int maxTessEvaluationOutputComponents;
|
||||
int maxTessEvaluationTextureImageUnits;
|
||||
int maxTessEvaluationUniformComponents;
|
||||
int maxTessPatchComponents;
|
||||
int maxPatchVertices;
|
||||
int maxTessGenLevel;
|
||||
int maxViewports;
|
||||
int maxVertexAtomicCounters;
|
||||
int maxTessControlAtomicCounters;
|
||||
int maxTessEvaluationAtomicCounters;
|
||||
int maxGeometryAtomicCounters;
|
||||
int maxFragmentAtomicCounters;
|
||||
int maxCombinedAtomicCounters;
|
||||
int maxAtomicCounterBindings;
|
||||
int maxVertexAtomicCounterBuffers;
|
||||
int maxTessControlAtomicCounterBuffers;
|
||||
int maxTessEvaluationAtomicCounterBuffers;
|
||||
int maxGeometryAtomicCounterBuffers;
|
||||
int maxFragmentAtomicCounterBuffers;
|
||||
int maxCombinedAtomicCounterBuffers;
|
||||
int maxAtomicCounterBufferSize;
|
||||
int maxTransformFeedbackBuffers;
|
||||
int maxTransformFeedbackInterleavedComponents;
|
||||
int maxCullDistances;
|
||||
int maxCombinedClipAndCullDistances;
|
||||
int maxSamples;
|
||||
int maxMeshOutputVerticesNV;
|
||||
int maxMeshOutputPrimitivesNV;
|
||||
int maxMeshWorkGroupSizeX_NV;
|
||||
int maxMeshWorkGroupSizeY_NV;
|
||||
int maxMeshWorkGroupSizeZ_NV;
|
||||
int maxTaskWorkGroupSizeX_NV;
|
||||
int maxTaskWorkGroupSizeY_NV;
|
||||
int maxTaskWorkGroupSizeZ_NV;
|
||||
int maxMeshViewCountNV;
|
||||
int maxDualSourceDrawBuffersEXT;
|
||||
|
||||
TLimits limits;
|
||||
};
|
||||
|
||||
#endif // _RESOURCE_LIMITS_INCLUDED_
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _SHHANDLE_INCLUDED_
|
||||
#define _SHHANDLE_INCLUDED_
|
||||
|
||||
//
|
||||
// Machine independent part of the compiler private objects
|
||||
// sent as ShHandle to the driver.
|
||||
//
|
||||
// This should not be included by driver code.
|
||||
//
|
||||
|
||||
#define SH_EXPORTING
|
||||
#include "../Public/ShaderLang.h"
|
||||
#include "../MachineIndependent/Versions.h"
|
||||
#include "InfoSink.h"
|
||||
|
||||
class TCompiler;
|
||||
class TLinker;
|
||||
class TUniformMap;
|
||||
|
||||
//
|
||||
// The base class used to back handles returned to the driver.
|
||||
//
|
||||
class TShHandleBase {
|
||||
public:
|
||||
TShHandleBase() { pool = new glslang::TPoolAllocator; }
|
||||
virtual ~TShHandleBase() { delete pool; }
|
||||
virtual TCompiler* getAsCompiler() { return 0; }
|
||||
virtual TLinker* getAsLinker() { return 0; }
|
||||
virtual TUniformMap* getAsUniformMap() { return 0; }
|
||||
virtual glslang::TPoolAllocator* getPool() const { return pool; }
|
||||
private:
|
||||
glslang::TPoolAllocator* pool;
|
||||
};
|
||||
|
||||
//
|
||||
// The base class for the machine dependent linker to derive from
|
||||
// for managing where uniforms live.
|
||||
//
|
||||
class TUniformMap : public TShHandleBase {
|
||||
public:
|
||||
TUniformMap() { }
|
||||
virtual ~TUniformMap() { }
|
||||
virtual TUniformMap* getAsUniformMap() { return this; }
|
||||
virtual int getLocation(const char* name) = 0;
|
||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
||||
TInfoSink infoSink;
|
||||
};
|
||||
|
||||
class TIntermNode;
|
||||
|
||||
//
|
||||
// The base class for the machine dependent compiler to derive from
|
||||
// for managing object code from the compile.
|
||||
//
|
||||
class TCompiler : public TShHandleBase {
|
||||
public:
|
||||
TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { }
|
||||
virtual ~TCompiler() { }
|
||||
EShLanguage getLanguage() { return language; }
|
||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
||||
|
||||
virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0;
|
||||
|
||||
virtual TCompiler* getAsCompiler() { return this; }
|
||||
virtual bool linkable() { return haveValidObjectCode; }
|
||||
|
||||
TInfoSink& infoSink;
|
||||
protected:
|
||||
TCompiler& operator=(TCompiler&);
|
||||
|
||||
EShLanguage language;
|
||||
bool haveValidObjectCode;
|
||||
};
|
||||
|
||||
//
|
||||
// Link operations are based on a list of compile results...
|
||||
//
|
||||
typedef glslang::TVector<TCompiler*> TCompilerList;
|
||||
typedef glslang::TVector<TShHandleBase*> THandleList;
|
||||
|
||||
//
|
||||
// The base class for the machine dependent linker to derive from
|
||||
// to manage the resulting executable.
|
||||
//
|
||||
|
||||
class TLinker : public TShHandleBase {
|
||||
public:
|
||||
TLinker(EShExecutable e, TInfoSink& iSink) :
|
||||
infoSink(iSink),
|
||||
executable(e),
|
||||
haveReturnableObjectCode(false),
|
||||
appAttributeBindings(0),
|
||||
fixedAttributeBindings(0),
|
||||
excludedAttributes(0),
|
||||
excludedCount(0),
|
||||
uniformBindings(0) { }
|
||||
virtual TLinker* getAsLinker() { return this; }
|
||||
virtual ~TLinker() { }
|
||||
virtual bool link(TCompilerList&, TUniformMap*) = 0;
|
||||
virtual bool link(THandleList&) { return false; }
|
||||
virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; }
|
||||
virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
|
||||
virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
|
||||
virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
|
||||
virtual ShBindingTable* getUniformBindings() const { return uniformBindings; }
|
||||
virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
|
||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
||||
TInfoSink& infoSink;
|
||||
protected:
|
||||
TLinker& operator=(TLinker&);
|
||||
EShExecutable executable;
|
||||
bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver
|
||||
|
||||
const ShBindingTable* appAttributeBindings;
|
||||
const ShBindingTable* fixedAttributeBindings;
|
||||
const int* excludedAttributes;
|
||||
int excludedCount;
|
||||
ShBindingTable* uniformBindings; // created by the linker
|
||||
};
|
||||
|
||||
//
|
||||
// This is the interface between the machine independent code
|
||||
// and the machine dependent code.
|
||||
//
|
||||
// The machine dependent code should derive from the classes
|
||||
// above. Then Construct*() and Delete*() will create and
|
||||
// destroy the machine dependent objects, which contain the
|
||||
// above machine independent information.
|
||||
//
|
||||
TCompiler* ConstructCompiler(EShLanguage, int);
|
||||
|
||||
TShHandleBase* ConstructLinker(EShExecutable, int);
|
||||
TShHandleBase* ConstructBindings();
|
||||
void DeleteLinker(TShHandleBase*);
|
||||
void DeleteBindingList(TShHandleBase* bindingList);
|
||||
|
||||
TUniformMap* ConstructUniformMap();
|
||||
void DeleteCompiler(TCompiler*);
|
||||
|
||||
void DeleteUniformMap(TUniformMap*);
|
||||
|
||||
#endif // _SHHANDLE_INCLUDED_
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,341 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
//
|
||||
// Implement types for tracking GLSL arrays, arrays of arrays, etc.
|
||||
//
|
||||
|
||||
#ifndef _ARRAYS_INCLUDED
|
||||
#define _ARRAYS_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
|
||||
const int UnsizedArraySize = 0;
|
||||
|
||||
class TIntermTyped;
|
||||
extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*);
|
||||
|
||||
// Specialization constants need both a nominal size and a node that defines
|
||||
// the specialization constant being used. Array types are the same when their
|
||||
// size and specialization constant nodes are the same.
|
||||
struct TArraySize {
|
||||
unsigned int size;
|
||||
TIntermTyped* node; // nullptr means no specialization constant node
|
||||
bool operator==(const TArraySize& rhs) const
|
||||
{
|
||||
if (size != rhs.size)
|
||||
return false;
|
||||
if (node == nullptr || rhs.node == nullptr)
|
||||
return node == rhs.node;
|
||||
|
||||
return SameSpecializationConstants(node, rhs.node);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
|
||||
// It has generic-container semantics, while TArraySizes has array-of-array semantics.
|
||||
// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
|
||||
//
|
||||
struct TSmallArrayVector {
|
||||
//
|
||||
// TODO: memory: TSmallArrayVector is intended to be smaller.
|
||||
// Almost all arrays could be handled by two sizes each fitting
|
||||
// in 16 bits, needing a real vector only in the cases where there
|
||||
// are more than 3 sizes or a size needing more than 16 bits.
|
||||
//
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
TSmallArrayVector() : sizes(nullptr) { }
|
||||
virtual ~TSmallArrayVector() { dealloc(); }
|
||||
|
||||
// For breaking into two non-shared copies, independently modifiable.
|
||||
TSmallArrayVector& operator=(const TSmallArrayVector& from)
|
||||
{
|
||||
if (from.sizes == nullptr)
|
||||
sizes = nullptr;
|
||||
else {
|
||||
alloc();
|
||||
*sizes = *from.sizes;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
if (sizes == nullptr)
|
||||
return 0;
|
||||
return (int)sizes->size();
|
||||
}
|
||||
|
||||
unsigned int frontSize() const
|
||||
{
|
||||
assert(sizes != nullptr && sizes->size() > 0);
|
||||
return sizes->front().size;
|
||||
}
|
||||
|
||||
TIntermTyped* frontNode() const
|
||||
{
|
||||
assert(sizes != nullptr && sizes->size() > 0);
|
||||
return sizes->front().node;
|
||||
}
|
||||
|
||||
void changeFront(unsigned int s)
|
||||
{
|
||||
assert(sizes != nullptr);
|
||||
// this should only happen for implicitly sized arrays, not specialization constants
|
||||
assert(sizes->front().node == nullptr);
|
||||
sizes->front().size = s;
|
||||
}
|
||||
|
||||
void push_back(unsigned int e, TIntermTyped* n)
|
||||
{
|
||||
alloc();
|
||||
TArraySize pair = { e, n };
|
||||
sizes->push_back(pair);
|
||||
}
|
||||
|
||||
void push_back(const TSmallArrayVector& newDims)
|
||||
{
|
||||
alloc();
|
||||
sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end());
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
assert(sizes != nullptr && sizes->size() > 0);
|
||||
if (sizes->size() == 1)
|
||||
dealloc();
|
||||
else
|
||||
sizes->erase(sizes->begin());
|
||||
}
|
||||
|
||||
// 'this' should currently not be holding anything, and copyNonFront
|
||||
// will make it hold a copy of all but the first element of rhs.
|
||||
// (This would be useful for making a type that is dereferenced by
|
||||
// one dimension.)
|
||||
void copyNonFront(const TSmallArrayVector& rhs)
|
||||
{
|
||||
assert(sizes == nullptr);
|
||||
if (rhs.size() > 1) {
|
||||
alloc();
|
||||
sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getDimSize(int i) const
|
||||
{
|
||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
||||
return (*sizes)[i].size;
|
||||
}
|
||||
|
||||
void setDimSize(int i, unsigned int size) const
|
||||
{
|
||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
||||
assert((*sizes)[i].node == nullptr);
|
||||
(*sizes)[i].size = size;
|
||||
}
|
||||
|
||||
TIntermTyped* getDimNode(int i) const
|
||||
{
|
||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
||||
return (*sizes)[i].node;
|
||||
}
|
||||
|
||||
bool operator==(const TSmallArrayVector& rhs) const
|
||||
{
|
||||
if (sizes == nullptr && rhs.sizes == nullptr)
|
||||
return true;
|
||||
if (sizes == nullptr || rhs.sizes == nullptr)
|
||||
return false;
|
||||
return *sizes == *rhs.sizes;
|
||||
}
|
||||
bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
|
||||
|
||||
protected:
|
||||
TSmallArrayVector(const TSmallArrayVector&);
|
||||
|
||||
void alloc()
|
||||
{
|
||||
if (sizes == nullptr)
|
||||
sizes = new TVector<TArraySize>;
|
||||
}
|
||||
void dealloc()
|
||||
{
|
||||
delete sizes;
|
||||
sizes = nullptr;
|
||||
}
|
||||
|
||||
TVector<TArraySize>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
|
||||
};
|
||||
|
||||
//
|
||||
// Represent an array, or array of arrays, to arbitrary depth. This is not
|
||||
// done through a hierarchy of types in a type tree, rather all contiguous arrayness
|
||||
// in the type hierarchy is localized into this single cumulative object.
|
||||
//
|
||||
// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
|
||||
// for the vast majority of types that are non-array types.
|
||||
//
|
||||
// Order Policy: these are all identical:
|
||||
// - left to right order within a contiguous set of ...[..][..][..]... in the source language
|
||||
// - index order 0, 1, 2, ... within the 'sizes' member below
|
||||
// - outer-most to inner-most
|
||||
//
|
||||
struct TArraySizes {
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
|
||||
TArraySizes() : implicitArraySize(1), variablyIndexed(false) { }
|
||||
|
||||
// For breaking into two non-shared copies, independently modifiable.
|
||||
TArraySizes& operator=(const TArraySizes& from)
|
||||
{
|
||||
implicitArraySize = from.implicitArraySize;
|
||||
variablyIndexed = from.variablyIndexed;
|
||||
sizes = from.sizes;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// translate from array-of-array semantics to container semantics
|
||||
int getNumDims() const { return sizes.size(); }
|
||||
int getDimSize(int dim) const { return sizes.getDimSize(dim); }
|
||||
TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); }
|
||||
void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); }
|
||||
int getOuterSize() const { return sizes.frontSize(); }
|
||||
TIntermTyped* getOuterNode() const { return sizes.frontNode(); }
|
||||
int getCumulativeSize() const
|
||||
{
|
||||
int size = 1;
|
||||
for (int d = 0; d < sizes.size(); ++d) {
|
||||
// this only makes sense in paths that have a known array size
|
||||
assert(sizes.getDimSize(d) != UnsizedArraySize);
|
||||
size *= sizes.getDimSize(d);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); }
|
||||
void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
|
||||
void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
|
||||
void addInnerSize(TArraySize pair) {
|
||||
sizes.push_back(pair.size, pair.node);
|
||||
}
|
||||
void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
|
||||
void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
|
||||
int getImplicitSize() const { return implicitArraySize; }
|
||||
void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); }
|
||||
bool isInnerUnsized() const
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool clearInnerUnsized()
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
|
||||
setDimSize(d, 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool isInnerSpecialization() const
|
||||
{
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes.getDimNode(d) != nullptr)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool isOuterSpecialization()
|
||||
{
|
||||
return sizes.getDimNode(0) != nullptr;
|
||||
}
|
||||
|
||||
bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
|
||||
bool isSized() const { return getOuterSize() != UnsizedArraySize; }
|
||||
void dereference() { sizes.pop_front(); }
|
||||
void copyDereferenced(const TArraySizes& rhs)
|
||||
{
|
||||
assert(sizes.size() == 0);
|
||||
if (rhs.sizes.size() > 1)
|
||||
sizes.copyNonFront(rhs.sizes);
|
||||
}
|
||||
|
||||
bool sameInnerArrayness(const TArraySizes& rhs) const
|
||||
{
|
||||
if (sizes.size() != rhs.sizes.size())
|
||||
return false;
|
||||
|
||||
for (int d = 1; d < sizes.size(); ++d) {
|
||||
if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) ||
|
||||
sizes.getDimNode(d) != rhs.sizes.getDimNode(d))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setVariablyIndexed() { variablyIndexed = true; }
|
||||
bool isVariablyIndexed() const { return variablyIndexed; }
|
||||
|
||||
bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; }
|
||||
bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; }
|
||||
|
||||
protected:
|
||||
TSmallArrayVector sizes;
|
||||
|
||||
TArraySizes(const TArraySizes&);
|
||||
|
||||
// For tracking maximum referenced compile-time constant index.
|
||||
// Applies only to the outer-most dimension. Potentially becomes
|
||||
// the implicit size of the array, if not variably indexed and
|
||||
// otherwise legal.
|
||||
int implicitArraySize;
|
||||
bool variablyIndexed; // true if array is indexed with a non compile-time constant
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _ARRAYS_INCLUDED_
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
This code is based on the glslang_c_interface implementation by Viktor Latypov
|
||||
**/
|
||||
|
||||
/**
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Viktor Latypov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**/
|
||||
|
||||
#ifndef GLSLANG_C_IFACE_H_INCLUDED
|
||||
#define GLSLANG_C_IFACE_H_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "glslang_c_shader_types.h"
|
||||
|
||||
typedef struct glslang_shader_s glslang_shader_t;
|
||||
typedef struct glslang_program_s glslang_program_t;
|
||||
|
||||
/* TLimits counterpart */
|
||||
typedef struct glslang_limits_s {
|
||||
bool non_inductive_for_loops;
|
||||
bool while_loops;
|
||||
bool do_while_loops;
|
||||
bool general_uniform_indexing;
|
||||
bool general_attribute_matrix_vector_indexing;
|
||||
bool general_varying_indexing;
|
||||
bool general_sampler_indexing;
|
||||
bool general_variable_indexing;
|
||||
bool general_constant_matrix_vector_indexing;
|
||||
} glslang_limits_t;
|
||||
|
||||
/* TBuiltInResource counterpart */
|
||||
typedef struct glslang_resource_s {
|
||||
int max_lights;
|
||||
int max_clip_planes;
|
||||
int max_texture_units;
|
||||
int max_texture_coords;
|
||||
int max_vertex_attribs;
|
||||
int max_vertex_uniform_components;
|
||||
int max_varying_floats;
|
||||
int max_vertex_texture_image_units;
|
||||
int max_combined_texture_image_units;
|
||||
int max_texture_image_units;
|
||||
int max_fragment_uniform_components;
|
||||
int max_draw_buffers;
|
||||
int max_vertex_uniform_vectors;
|
||||
int max_varying_vectors;
|
||||
int max_fragment_uniform_vectors;
|
||||
int max_vertex_output_vectors;
|
||||
int max_fragment_input_vectors;
|
||||
int min_program_texel_offset;
|
||||
int max_program_texel_offset;
|
||||
int max_clip_distances;
|
||||
int max_compute_work_group_count_x;
|
||||
int max_compute_work_group_count_y;
|
||||
int max_compute_work_group_count_z;
|
||||
int max_compute_work_group_size_x;
|
||||
int max_compute_work_group_size_y;
|
||||
int max_compute_work_group_size_z;
|
||||
int max_compute_uniform_components;
|
||||
int max_compute_texture_image_units;
|
||||
int max_compute_image_uniforms;
|
||||
int max_compute_atomic_counters;
|
||||
int max_compute_atomic_counter_buffers;
|
||||
int max_varying_components;
|
||||
int max_vertex_output_components;
|
||||
int max_geometry_input_components;
|
||||
int max_geometry_output_components;
|
||||
int max_fragment_input_components;
|
||||
int max_image_units;
|
||||
int max_combined_image_units_and_fragment_outputs;
|
||||
int max_combined_shader_output_resources;
|
||||
int max_image_samples;
|
||||
int max_vertex_image_uniforms;
|
||||
int max_tess_control_image_uniforms;
|
||||
int max_tess_evaluation_image_uniforms;
|
||||
int max_geometry_image_uniforms;
|
||||
int max_fragment_image_uniforms;
|
||||
int max_combined_image_uniforms;
|
||||
int max_geometry_texture_image_units;
|
||||
int max_geometry_output_vertices;
|
||||
int max_geometry_total_output_components;
|
||||
int max_geometry_uniform_components;
|
||||
int max_geometry_varying_components;
|
||||
int max_tess_control_input_components;
|
||||
int max_tess_control_output_components;
|
||||
int max_tess_control_texture_image_units;
|
||||
int max_tess_control_uniform_components;
|
||||
int max_tess_control_total_output_components;
|
||||
int max_tess_evaluation_input_components;
|
||||
int max_tess_evaluation_output_components;
|
||||
int max_tess_evaluation_texture_image_units;
|
||||
int max_tess_evaluation_uniform_components;
|
||||
int max_tess_patch_components;
|
||||
int max_patch_vertices;
|
||||
int max_tess_gen_level;
|
||||
int max_viewports;
|
||||
int max_vertex_atomic_counters;
|
||||
int max_tess_control_atomic_counters;
|
||||
int max_tess_evaluation_atomic_counters;
|
||||
int max_geometry_atomic_counters;
|
||||
int max_fragment_atomic_counters;
|
||||
int max_combined_atomic_counters;
|
||||
int max_atomic_counter_bindings;
|
||||
int max_vertex_atomic_counter_buffers;
|
||||
int max_tess_control_atomic_counter_buffers;
|
||||
int max_tess_evaluation_atomic_counter_buffers;
|
||||
int max_geometry_atomic_counter_buffers;
|
||||
int max_fragment_atomic_counter_buffers;
|
||||
int max_combined_atomic_counter_buffers;
|
||||
int max_atomic_counter_buffer_size;
|
||||
int max_transform_feedback_buffers;
|
||||
int max_transform_feedback_interleaved_components;
|
||||
int max_cull_distances;
|
||||
int max_combined_clip_and_cull_distances;
|
||||
int max_samples;
|
||||
int max_mesh_output_vertices_nv;
|
||||
int max_mesh_output_primitives_nv;
|
||||
int max_mesh_work_group_size_x_nv;
|
||||
int max_mesh_work_group_size_y_nv;
|
||||
int max_mesh_work_group_size_z_nv;
|
||||
int max_task_work_group_size_x_nv;
|
||||
int max_task_work_group_size_y_nv;
|
||||
int max_task_work_group_size_z_nv;
|
||||
int max_mesh_view_count_nv;
|
||||
int maxDualSourceDrawBuffersEXT;
|
||||
|
||||
glslang_limits_t limits;
|
||||
} glslang_resource_t;
|
||||
|
||||
typedef struct glslang_input_s {
|
||||
glslang_source_t language;
|
||||
glslang_stage_t stage;
|
||||
glslang_client_t client;
|
||||
glslang_target_client_version_t client_version;
|
||||
glslang_target_language_t target_language;
|
||||
glslang_target_language_version_t target_language_version;
|
||||
/** Shader source code */
|
||||
const char* code;
|
||||
int default_version;
|
||||
glslang_profile_t default_profile;
|
||||
int force_default_version_and_profile;
|
||||
int forward_compatible;
|
||||
glslang_messages_t messages;
|
||||
const glslang_resource_t* resource;
|
||||
} glslang_input_t;
|
||||
|
||||
/* Inclusion result structure allocated by C include_local/include_system callbacks */
|
||||
typedef struct glsl_include_result_s {
|
||||
/* Header file name or NULL if inclusion failed */
|
||||
const char* header_name;
|
||||
|
||||
/* Header contents or NULL */
|
||||
const char* header_data;
|
||||
size_t header_length;
|
||||
|
||||
} glsl_include_result_t;
|
||||
|
||||
/* Callback for local file inclusion */
|
||||
typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name,
|
||||
size_t include_depth);
|
||||
|
||||
/* Callback for system file inclusion */
|
||||
typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name,
|
||||
const char* includer_name, size_t include_depth);
|
||||
|
||||
/* Callback for include result destruction */
|
||||
typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result);
|
||||
|
||||
/* Collection of callbacks for GLSL preprocessor */
|
||||
typedef struct glsl_include_callbacks_s {
|
||||
glsl_include_system_func include_system;
|
||||
glsl_include_local_func include_local;
|
||||
glsl_free_include_result_func free_include_result;
|
||||
} glsl_include_callbacks_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef GLSLANG_IS_SHARED_LIBRARY
|
||||
#ifdef _WIN32
|
||||
#ifdef GLSLANG_EXPORTING
|
||||
#define GLSLANG_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define GLSLANG_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#elif __GNUC__ >= 4
|
||||
#define GLSLANG_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif // GLSLANG_IS_SHARED_LIBRARY
|
||||
|
||||
#ifndef GLSLANG_EXPORT
|
||||
#define GLSLANG_EXPORT
|
||||
#endif
|
||||
|
||||
GLSLANG_EXPORT int glslang_initialize_process();
|
||||
GLSLANG_EXPORT void glslang_finalize_process();
|
||||
|
||||
GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
|
||||
GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader);
|
||||
GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
|
||||
GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
|
||||
GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
|
||||
GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader);
|
||||
GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
|
||||
|
||||
GLSLANG_EXPORT glslang_program_t* glslang_program_create();
|
||||
GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program);
|
||||
GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
|
||||
GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
|
||||
GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
|
||||
GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
|
||||
GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);
|
||||
GLSLANG_EXPORT unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program);
|
||||
GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t* program);
|
||||
GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program);
|
||||
GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
This code is based on the glslang_c_interface implementation by Viktor Latypov
|
||||
**/
|
||||
|
||||
/**
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2019, Viktor Latypov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**/
|
||||
|
||||
#ifndef C_SHADER_TYPES_H_INCLUDED
|
||||
#define C_SHADER_TYPES_H_INCLUDED
|
||||
|
||||
#define LAST_ELEMENT_MARKER(x) x
|
||||
|
||||
/* EShLanguage counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_STAGE_VERTEX,
|
||||
GLSLANG_STAGE_TESSCONTROL,
|
||||
GLSLANG_STAGE_TESSEVALUATION,
|
||||
GLSLANG_STAGE_GEOMETRY,
|
||||
GLSLANG_STAGE_FRAGMENT,
|
||||
GLSLANG_STAGE_COMPUTE,
|
||||
GLSLANG_STAGE_RAYGEN_NV,
|
||||
GLSLANG_STAGE_INTERSECT_NV,
|
||||
GLSLANG_STAGE_ANYHIT_NV,
|
||||
GLSLANG_STAGE_CLOSESTHIT_NV,
|
||||
GLSLANG_STAGE_MISS_NV,
|
||||
GLSLANG_STAGE_CALLABLE_NV,
|
||||
GLSLANG_STAGE_TASK_NV,
|
||||
GLSLANG_STAGE_MESH_NV,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT),
|
||||
} glslang_stage_t; // would be better as stage, but this is ancient now
|
||||
|
||||
/* EShLanguageMask counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX),
|
||||
GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL),
|
||||
GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION),
|
||||
GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY),
|
||||
GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT),
|
||||
GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE),
|
||||
GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV),
|
||||
GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV),
|
||||
GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV),
|
||||
GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV),
|
||||
GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV),
|
||||
GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV),
|
||||
GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV),
|
||||
GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV),
|
||||
LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT),
|
||||
} glslang_stage_mask_t;
|
||||
|
||||
/* EShSource counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_SOURCE_NONE,
|
||||
GLSLANG_SOURCE_GLSL,
|
||||
GLSLANG_SOURCE_HLSL,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT),
|
||||
} glslang_source_t;
|
||||
|
||||
/* EShClient counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_CLIENT_NONE,
|
||||
GLSLANG_CLIENT_VULKAN,
|
||||
GLSLANG_CLIENT_OPENGL,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT),
|
||||
} glslang_client_t;
|
||||
|
||||
/* EShTargetLanguage counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_TARGET_NONE,
|
||||
GLSLANG_TARGET_SPV,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT),
|
||||
} glslang_target_language_t;
|
||||
|
||||
/* SH_TARGET_ClientVersion counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_TARGET_VULKAN_1_0 = (1 << 22),
|
||||
GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12),
|
||||
GLSLANG_TARGET_VULKAN_1_2 = (1 << 22) | (2 << 12),
|
||||
GLSLANG_TARGET_OPENGL_450 = 450,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT = 4),
|
||||
} glslang_target_client_version_t;
|
||||
|
||||
/* SH_TARGET_LanguageVersion counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_TARGET_SPV_1_0 = (1 << 16),
|
||||
GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8),
|
||||
GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8),
|
||||
GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8),
|
||||
GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8),
|
||||
GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8),
|
||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT = 6),
|
||||
} glslang_target_language_version_t;
|
||||
|
||||
/* EShExecutable counterpart */
|
||||
typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t;
|
||||
|
||||
/* EShOptimizationLevel counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_OPT_NO_GENERATION,
|
||||
GLSLANG_OPT_NONE,
|
||||
GLSLANG_OPT_SIMPLE,
|
||||
GLSLANG_OPT_FULL,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT),
|
||||
} glslang_optimization_level_t;
|
||||
|
||||
/* EShTextureSamplerTransformMode counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_TEX_SAMP_TRANS_KEEP,
|
||||
GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER,
|
||||
LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT),
|
||||
} glslang_texture_sampler_transform_mode_t;
|
||||
|
||||
/* EShMessages counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_MSG_DEFAULT_BIT = 0,
|
||||
GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0),
|
||||
GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1),
|
||||
GLSLANG_MSG_AST_BIT = (1 << 2),
|
||||
GLSLANG_MSG_SPV_RULES_BIT = (1 << 3),
|
||||
GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4),
|
||||
GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5),
|
||||
GLSLANG_MSG_READ_HLSL_BIT = (1 << 6),
|
||||
GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7),
|
||||
GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8),
|
||||
GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9),
|
||||
GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10),
|
||||
GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11),
|
||||
GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12),
|
||||
GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13),
|
||||
GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14),
|
||||
LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT),
|
||||
} glslang_messages_t;
|
||||
|
||||
/* EShReflectionOptions counterpart */
|
||||
typedef enum {
|
||||
GLSLANG_REFLECTION_DEFAULT_BIT = 0,
|
||||
GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0),
|
||||
GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1),
|
||||
GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2),
|
||||
GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3),
|
||||
GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4),
|
||||
GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5),
|
||||
GLSLANG_REFLECTION_ALL_IO_VARIABLES_BIT = (1 << 6),
|
||||
GLSLANG_REFLECTION_SHARED_STD140_SSBO_BIT = (1 << 7),
|
||||
GLSLANG_REFLECTION_SHARED_STD140_UBO_BIT = (1 << 8),
|
||||
LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT),
|
||||
} glslang_reflection_options_t;
|
||||
|
||||
/* EProfile counterpart (from Versions.h) */
|
||||
typedef enum {
|
||||
GLSLANG_BAD_PROFILE = 0,
|
||||
GLSLANG_NO_PROFILE = (1 << 0),
|
||||
GLSLANG_CORE_PROFILE = (1 << 1),
|
||||
GLSLANG_COMPATIBILITY_PROFILE = (1 << 2),
|
||||
GLSLANG_ES_PROFILE = (1 << 3),
|
||||
LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT),
|
||||
} glslang_profile_t;
|
||||
|
||||
#undef LAST_ELEMENT_MARKER
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,112 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2013-2016 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _INITIALIZE_INCLUDED_
|
||||
#define _INITIALIZE_INCLUDED_
|
||||
|
||||
#include "../Include/ResourceLimits.h"
|
||||
#include "../Include/Common.h"
|
||||
#include "../Include/ShHandle.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Versions.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// This is made to hold parseable strings for almost all the built-in
|
||||
// functions and variables for one specific combination of version
|
||||
// and profile. (Some still need to be added programmatically.)
|
||||
// This is a base class for language-specific derivations, which
|
||||
// can be used for language independent builtins.
|
||||
//
|
||||
// The strings are organized by
|
||||
// commonBuiltins: intersection of all stages' built-ins, processed just once
|
||||
// stageBuiltins[]: anything a stage needs that's not in commonBuiltins
|
||||
//
|
||||
class TBuiltInParseables {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
TBuiltInParseables();
|
||||
virtual ~TBuiltInParseables();
|
||||
virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0;
|
||||
virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0;
|
||||
virtual const TString& getCommonString() const { return commonBuiltins; }
|
||||
virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; }
|
||||
|
||||
virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0;
|
||||
virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0;
|
||||
|
||||
protected:
|
||||
TString commonBuiltins;
|
||||
TString stageBuiltins[EShLangCount];
|
||||
};
|
||||
|
||||
//
|
||||
// This is a GLSL specific derivation of TBuiltInParseables. To present a stable
|
||||
// interface and match other similar code, it is called TBuiltIns, rather
|
||||
// than TBuiltInParseablesGlsl.
|
||||
//
|
||||
class TBuiltIns : public TBuiltInParseables {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
TBuiltIns();
|
||||
virtual ~TBuiltIns();
|
||||
void initialize(int version, EProfile, const SpvVersion& spvVersion);
|
||||
void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage);
|
||||
|
||||
void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable);
|
||||
void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources);
|
||||
|
||||
protected:
|
||||
void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion);
|
||||
void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&);
|
||||
void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion);
|
||||
void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile);
|
||||
void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
||||
void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
||||
void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
||||
void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
||||
|
||||
// Helpers for making textual representations of the permutations
|
||||
// of texturing/imaging functions.
|
||||
const char* postfixes[5];
|
||||
const char* prefixes[EbtNumTypes];
|
||||
int dimMap[EsdNumDims];
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _INITIALIZE_INCLUDED_
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
//
|
||||
// Copyright (C) 2016 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include "reflection.h"
|
||||
#include "localintermediate.h"
|
||||
|
||||
#include "gl_types.h"
|
||||
|
||||
#include <list>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// The traverser: mostly pass through, except
|
||||
// - processing function-call nodes to push live functions onto the stack of functions to process
|
||||
// - processing selection nodes to trim semantically dead code
|
||||
//
|
||||
// This is in the glslang namespace directly so it can be a friend of TReflection.
|
||||
// This can be derived from to implement reflection database traversers or
|
||||
// binding mappers: anything that wants to traverse the live subset of the tree.
|
||||
//
|
||||
|
||||
class TLiveTraverser : public TIntermTraverser {
|
||||
public:
|
||||
TLiveTraverser(const TIntermediate& i, bool traverseAll = false,
|
||||
bool preVisit = true, bool inVisit = false, bool postVisit = false) :
|
||||
TIntermTraverser(preVisit, inVisit, postVisit),
|
||||
intermediate(i), traverseAll(traverseAll)
|
||||
{ }
|
||||
|
||||
//
|
||||
// Given a function name, find its subroot in the tree, and push it onto the stack of
|
||||
// functions left to process.
|
||||
//
|
||||
void pushFunction(const TString& name)
|
||||
{
|
||||
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
|
||||
for (unsigned int f = 0; f < globals.size(); ++f) {
|
||||
TIntermAggregate* candidate = globals[f]->getAsAggregate();
|
||||
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
|
||||
destinations.push_back(candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pushGlobalReference(const TString& name)
|
||||
{
|
||||
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
|
||||
for (unsigned int f = 0; f < globals.size(); ++f) {
|
||||
TIntermAggregate* candidate = globals[f]->getAsAggregate();
|
||||
if (candidate && candidate->getOp() == EOpSequence &&
|
||||
candidate->getSequence().size() == 1 &&
|
||||
candidate->getSequence()[0]->getAsBinaryNode()) {
|
||||
TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode();
|
||||
TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode();
|
||||
if (symbol && symbol->getQualifier().storage == EvqGlobal &&
|
||||
symbol->getName() == name) {
|
||||
destinations.push_back(candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::list<TIntermAggregate*> TDestinationStack;
|
||||
TDestinationStack destinations;
|
||||
|
||||
protected:
|
||||
// To catch which function calls are not dead, and hence which functions must be visited.
|
||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node)
|
||||
{
|
||||
if (!traverseAll)
|
||||
if (node->getOp() == EOpFunctionCall)
|
||||
addFunctionCall(node);
|
||||
|
||||
return true; // traverse this subtree
|
||||
}
|
||||
|
||||
// To prune semantically dead paths.
|
||||
virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node)
|
||||
{
|
||||
if (traverseAll)
|
||||
return true; // traverse all code
|
||||
|
||||
TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
|
||||
if (constant) {
|
||||
// cull the path that is dead
|
||||
if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
|
||||
node->getTrueBlock()->traverse(this);
|
||||
if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
|
||||
node->getFalseBlock()->traverse(this);
|
||||
|
||||
return false; // don't traverse any more, we did it all above
|
||||
} else
|
||||
return true; // traverse the whole subtree
|
||||
}
|
||||
|
||||
// Track live functions as well as uniforms, so that we don't visit dead functions
|
||||
// and only visit each function once.
|
||||
void addFunctionCall(TIntermAggregate* call)
|
||||
{
|
||||
// just use the map to ensure we process each function at most once
|
||||
if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
|
||||
liveFunctions.insert(call->getName());
|
||||
pushFunction(call->getName());
|
||||
}
|
||||
}
|
||||
|
||||
void addGlobalReference(const TString& name)
|
||||
{
|
||||
// just use the map to ensure we process each global at most once
|
||||
if (liveGlobals.find(name) == liveGlobals.end()) {
|
||||
liveGlobals.insert(name);
|
||||
pushGlobalReference(name);
|
||||
}
|
||||
}
|
||||
|
||||
const TIntermediate& intermediate;
|
||||
typedef std::unordered_set<TString> TLiveFunctions;
|
||||
TLiveFunctions liveFunctions;
|
||||
typedef std::unordered_set<TString> TLiveGlobals;
|
||||
TLiveGlobals liveGlobals;
|
||||
bool traverseAll;
|
||||
|
||||
private:
|
||||
// prevent copy & copy construct
|
||||
TLiveTraverser(TLiveTraverser&);
|
||||
TLiveTraverser& operator=(TLiveTraverser&);
|
||||
};
|
||||
|
||||
} // namespace glslang
|
||||
|
|
@ -0,0 +1,571 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
//
|
||||
// This header defines a two-level parse-helper hierarchy, derived from
|
||||
// TParseVersions:
|
||||
// - TParseContextBase: sharable across multiple parsers
|
||||
// - TParseContext: GLSL specific helper
|
||||
//
|
||||
|
||||
#ifndef _PARSER_HELPER_INCLUDED_
|
||||
#define _PARSER_HELPER_INCLUDED_
|
||||
|
||||
#include <cstdarg>
|
||||
#include <functional>
|
||||
|
||||
#include "parseVersions.h"
|
||||
#include "../Include/ShHandle.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "localintermediate.h"
|
||||
#include "Scan.h"
|
||||
#include "attribute.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
struct TPragma {
|
||||
TPragma(bool o, bool d) : optimize(o), debug(d) { }
|
||||
bool optimize;
|
||||
bool debug;
|
||||
TPragmaTable pragmaTable;
|
||||
};
|
||||
|
||||
class TScanContext;
|
||||
class TPpContext;
|
||||
|
||||
typedef std::set<long long> TIdSetType;
|
||||
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
|
||||
|
||||
//
|
||||
// Sharable code (as well as what's in TParseVersions) across
|
||||
// parse helpers.
|
||||
//
|
||||
class TParseContextBase : public TParseVersions {
|
||||
public:
|
||||
TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
|
||||
EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
|
||||
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
|
||||
const TString* entryPoint = nullptr)
|
||||
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
|
||||
scopeMangler("::"),
|
||||
symbolTable(symbolTable),
|
||||
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
|
||||
currentFunctionType(nullptr),
|
||||
postEntryPointReturn(false),
|
||||
contextPragma(true, false),
|
||||
beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
|
||||
parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
|
||||
limits(resources.limits),
|
||||
globalUniformBlock(nullptr),
|
||||
globalUniformBinding(TQualifier::layoutBindingEnd),
|
||||
globalUniformSet(TQualifier::layoutSetEnd),
|
||||
atomicCounterBlockSet(TQualifier::layoutSetEnd)
|
||||
{
|
||||
if (entryPoint != nullptr)
|
||||
sourceEntryPointName = *entryPoint;
|
||||
}
|
||||
virtual ~TParseContextBase() { }
|
||||
|
||||
#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
|
||||
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...);
|
||||
#endif
|
||||
|
||||
virtual void setLimits(const TBuiltInResource&) = 0;
|
||||
|
||||
void checkIndex(const TSourceLoc&, const TType&, int& index);
|
||||
|
||||
EShLanguage getLanguage() const { return language; }
|
||||
void setScanContext(TScanContext* c) { scanContext = c; }
|
||||
TScanContext* getScanContext() const { return scanContext; }
|
||||
void setPpContext(TPpContext* c) { ppContext = c; }
|
||||
TPpContext* getPpContext() const { return ppContext; }
|
||||
|
||||
virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
|
||||
virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
|
||||
virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
|
||||
virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
|
||||
virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
|
||||
|
||||
virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
|
||||
virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
|
||||
virtual bool lineDirectiveShouldSetNextLine() const = 0;
|
||||
virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
|
||||
|
||||
virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
|
||||
|
||||
virtual void notifyVersion(int line, int version, const char* type_string)
|
||||
{
|
||||
if (versionCallback)
|
||||
versionCallback(line, version, type_string);
|
||||
}
|
||||
virtual void notifyErrorDirective(int line, const char* error_message)
|
||||
{
|
||||
if (errorCallback)
|
||||
errorCallback(line, error_message);
|
||||
}
|
||||
virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
|
||||
{
|
||||
if (lineCallback)
|
||||
lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
|
||||
}
|
||||
virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
|
||||
{
|
||||
if (extensionCallback)
|
||||
extensionCallback(line, extension, behavior);
|
||||
}
|
||||
|
||||
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
|
||||
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
|
||||
|
||||
// Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
|
||||
virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
|
||||
|
||||
// Potentially rename shader entry point function
|
||||
void renameShaderFunction(TString*& name) const
|
||||
{
|
||||
// Replace the entry point name given in the shader with the real entry point name,
|
||||
// if there is a substitution.
|
||||
if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0)
|
||||
name = NewPoolTString(intermediate.getEntryPointName().c_str());
|
||||
}
|
||||
|
||||
virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
|
||||
const char* const scopeMangler;
|
||||
|
||||
// Basic parsing state, easily accessible to the grammar
|
||||
|
||||
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
||||
int statementNestingLevel; // 0 if outside all flow control or compound statements
|
||||
int loopNestingLevel; // 0 if outside all loops
|
||||
int structNestingLevel; // 0 if outside structures
|
||||
int blockNestingLevel; // 0 if outside blocks
|
||||
int controlFlowNestingLevel; // 0 if outside all flow control
|
||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
||||
bool functionReturnsValue; // true if a non-void function has a return
|
||||
// if inside a function, true if the function is the entry point and this is after a return statement
|
||||
bool postEntryPointReturn;
|
||||
// case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
|
||||
TList<TIntermSequence*> switchSequenceStack;
|
||||
// the statementNestingLevel the current switch statement is at, which must match the level of its case statements
|
||||
TList<int> switchLevel;
|
||||
struct TPragma contextPragma;
|
||||
int beginInvocationInterlockCount;
|
||||
int endInvocationInterlockCount;
|
||||
|
||||
protected:
|
||||
TParseContextBase(TParseContextBase&);
|
||||
TParseContextBase& operator=(TParseContextBase&);
|
||||
|
||||
const bool parsingBuiltins; // true if parsing built-in symbols/functions
|
||||
TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
|
||||
TScanContext* scanContext;
|
||||
TPpContext* ppContext;
|
||||
TBuiltInResource resources;
|
||||
TLimits& limits;
|
||||
TString sourceEntryPointName;
|
||||
|
||||
// These, if set, will be called when a line, pragma ... is preprocessed.
|
||||
// They will be called with any parameters to the original directive.
|
||||
std::function<void(int, int, bool, int, const char*)> lineCallback;
|
||||
std::function<void(int, const TVector<TString>&)> pragmaCallback;
|
||||
std::function<void(int, int, const char*)> versionCallback;
|
||||
std::function<void(int, const char*, const char*)> extensionCallback;
|
||||
std::function<void(int, const char*)> errorCallback;
|
||||
|
||||
// see implementation for detail
|
||||
const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&,
|
||||
std::function<bool(const TType&, const TType&, TOperator, int arg)>,
|
||||
std::function<bool(const TType&, const TType&, const TType&)>,
|
||||
/* output */ bool& tie);
|
||||
|
||||
virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size,
|
||||
TSwizzleSelectors<TVectorSelector>&);
|
||||
|
||||
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
|
||||
TVariable* globalUniformBlock; // the actual block, inserted into the symbol table
|
||||
unsigned int globalUniformBinding; // the block's binding number
|
||||
unsigned int globalUniformSet; // the block's set number
|
||||
int firstNewMember; // the index of the first member not yet inserted into the symbol table
|
||||
// override this to set the language-specific name
|
||||
virtual const char* getGlobalUniformBlockName() const { return ""; }
|
||||
virtual void setUniformBlockDefaults(TType&) const { }
|
||||
virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
|
||||
|
||||
// Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
|
||||
TMap<int, TVariable*> atomicCounterBuffers;
|
||||
unsigned int atomicCounterBlockSet;
|
||||
TMap<int, int> atomicCounterBlockFirstNewMember;
|
||||
// override this to set the language-specific name
|
||||
virtual const char* getAtomicCounterBlockName() const { return ""; }
|
||||
virtual void setAtomicCounterBlockDefaults(TType&) const {}
|
||||
virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
|
||||
bool isAtomicCounterBlock(const TSymbol& symbol) {
|
||||
const TVariable* var = symbol.getAsVariable();
|
||||
if (!var)
|
||||
return false;
|
||||
const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
|
||||
return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
|
||||
}
|
||||
|
||||
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||
va_list args);
|
||||
virtual void trackLinkage(TSymbol& symbol);
|
||||
virtual void makeEditable(TSymbol*&);
|
||||
virtual TVariable* getEditableVariable(const char* name);
|
||||
virtual void finish();
|
||||
};
|
||||
|
||||
//
|
||||
// Manage the state for when to respect precision qualifiers and when to warn about
|
||||
// the defaults being different than might be expected.
|
||||
//
|
||||
class TPrecisionManager {
|
||||
public:
|
||||
TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
|
||||
virtual ~TPrecisionManager() {}
|
||||
|
||||
void respectPrecisionQualifiers() { obey = true; }
|
||||
bool respectingPrecisionQualifiers() const { return obey; }
|
||||
bool shouldWarnAboutDefaults() const { return warn; }
|
||||
void defaultWarningGiven() { warn = false; }
|
||||
void warnAboutDefaults() { warn = true; }
|
||||
void explicitIntDefaultSeen()
|
||||
{
|
||||
explicitIntDefault = true;
|
||||
if (explicitFloatDefault)
|
||||
warn = false;
|
||||
}
|
||||
void explicitFloatDefaultSeen()
|
||||
{
|
||||
explicitFloatDefault = true;
|
||||
if (explicitIntDefault)
|
||||
warn = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool obey; // respect precision qualifiers
|
||||
bool warn; // need to give a warning about the defaults
|
||||
bool explicitIntDefault; // user set the default for int/uint
|
||||
bool explicitFloatDefault; // user set the default for float
|
||||
};
|
||||
|
||||
//
|
||||
// GLSL-specific parse helper. Should have GLSL in the name, but that's
|
||||
// too big of a change for comparing branches at the moment, and perhaps
|
||||
// impacts downstream consumers as well.
|
||||
//
|
||||
class TParseContext : public TParseContextBase {
|
||||
public:
|
||||
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
|
||||
bool forwardCompatible = false, EShMessages messages = EShMsgDefault,
|
||||
const TString* entryPoint = nullptr);
|
||||
virtual ~TParseContext();
|
||||
|
||||
bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); }
|
||||
void setPrecisionDefaults();
|
||||
|
||||
void setLimits(const TBuiltInResource&) override;
|
||||
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
|
||||
void parserError(const char* s); // for bison's yyerror
|
||||
|
||||
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
|
||||
virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
|
||||
|
||||
void reservedErrorCheck(const TSourceLoc&, const TString&);
|
||||
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
|
||||
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
|
||||
bool lineDirectiveShouldSetNextLine() const override;
|
||||
bool builtInName(const TString&);
|
||||
|
||||
void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
|
||||
TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
|
||||
TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
|
||||
void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
void makeEditable(TSymbol*&) override;
|
||||
void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
||||
#endif
|
||||
bool isIoResizeArray(const TType&) const;
|
||||
void fixIoArraySize(const TSourceLoc&, TType&);
|
||||
void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
|
||||
void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
|
||||
int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const;
|
||||
void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
|
||||
|
||||
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
||||
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
||||
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
||||
TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
||||
void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
|
||||
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
||||
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||
TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function);
|
||||
void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
|
||||
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
|
||||
void checkLocation(const TSourceLoc&, TOperator);
|
||||
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
|
||||
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
|
||||
TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
||||
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
|
||||
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
|
||||
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
|
||||
void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
|
||||
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
|
||||
void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
|
||||
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
|
||||
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
|
||||
|
||||
TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||
// returns true if the variable was remapped to something else
|
||||
bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
|
||||
|
||||
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
||||
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
void variableCheck(TIntermTyped*& nodePtr);
|
||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
void constantValueCheck(TIntermTyped* node, const char* token);
|
||||
void integerCheck(const TIntermTyped* node, const char* token);
|
||||
void globalCheck(const TSourceLoc&, const char* token);
|
||||
bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
|
||||
bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
|
||||
void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType);
|
||||
bool arrayQualifierError(const TSourceLoc&, const TQualifier&);
|
||||
bool arrayError(const TSourceLoc&, const TType&);
|
||||
void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
|
||||
void structArrayCheck(const TSourceLoc&, const TType& structure);
|
||||
void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember);
|
||||
void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*);
|
||||
bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
|
||||
void boolCheck(const TSourceLoc&, const TIntermTyped*);
|
||||
void boolCheck(const TSourceLoc&, const TPublicType&);
|
||||
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
|
||||
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
||||
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
|
||||
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
||||
void memberQualifierCheck(glslang::TPublicType&);
|
||||
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
|
||||
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
|
||||
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
||||
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
|
||||
void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier);
|
||||
int computeSamplerTypeIndex(TSampler&);
|
||||
TPrecisionQualifier getDefaultPrecision(TPublicType&);
|
||||
void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&);
|
||||
void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type);
|
||||
bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
|
||||
TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
|
||||
void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
|
||||
void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
|
||||
void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
|
||||
void nestedBlockCheck(const TSourceLoc&);
|
||||
void nestedStructCheck(const TSourceLoc&);
|
||||
void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void referenceCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void structTypeCheck(const TSourceLoc&, TPublicType&);
|
||||
void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
|
||||
void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
|
||||
void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
|
||||
|
||||
void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
|
||||
void constantIndexExpressionCheck(TIntermNode*);
|
||||
|
||||
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
|
||||
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
|
||||
void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
|
||||
void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
|
||||
void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
|
||||
void layoutTypeCheck(const TSourceLoc&, const TType&);
|
||||
void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
|
||||
void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
|
||||
void fixOffset(const TSourceLoc&, TSymbol&);
|
||||
|
||||
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
||||
void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
|
||||
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
|
||||
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
|
||||
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
|
||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
||||
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
|
||||
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||
void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
|
||||
void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
|
||||
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
|
||||
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
||||
void fixXfbOffsets(TQualifier&, TTypeList&);
|
||||
void fixBlockUniformOffsets(TQualifier&, TTypeList&);
|
||||
void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
|
||||
void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
|
||||
void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
|
||||
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
||||
void invariantCheck(const TSourceLoc&, const TQualifier&);
|
||||
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
||||
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
|
||||
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
TAttributeType attributeFromName(const TString& name) const;
|
||||
TAttributes* makeAttributes(const TString& identifier) const;
|
||||
TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
|
||||
TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
|
||||
|
||||
// Determine selection control from attributes
|
||||
void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
|
||||
void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
|
||||
// Determine loop control from attributes
|
||||
void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
|
||||
#endif
|
||||
|
||||
void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
|
||||
|
||||
protected:
|
||||
void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
|
||||
void inheritGlobalDefaults(TQualifier& dst) const;
|
||||
TVariable* makeInternalVariable(const char* name, const TType&) const;
|
||||
TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
|
||||
void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
|
||||
void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&);
|
||||
bool isRuntimeLength(const TIntermTyped&) const;
|
||||
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
|
||||
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
|
||||
#ifndef GLSLANG_WEB
|
||||
void finish() override;
|
||||
#endif
|
||||
|
||||
virtual const char* getGlobalUniformBlockName() const override;
|
||||
virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
|
||||
virtual void setUniformBlockDefaults(TType& block) const override;
|
||||
|
||||
virtual const char* getAtomicCounterBlockName() const override;
|
||||
virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
|
||||
virtual void setAtomicCounterBlockDefaults(TType& block) const override;
|
||||
|
||||
public:
|
||||
//
|
||||
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
|
||||
//
|
||||
|
||||
// Current state of parsing
|
||||
bool inMain; // if inside a function, true if the function is main
|
||||
const TString* blockName;
|
||||
TQualifier currentBlockQualifier;
|
||||
TPrecisionQualifier defaultPrecision[EbtNumTypes];
|
||||
TBuiltInResource resources;
|
||||
TLimits& limits;
|
||||
|
||||
protected:
|
||||
TParseContext(TParseContext&);
|
||||
TParseContext& operator=(TParseContext&);
|
||||
|
||||
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
|
||||
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
|
||||
TPrecisionManager precisionManager;
|
||||
TQualifier globalBufferDefaults;
|
||||
TQualifier globalUniformDefaults;
|
||||
TQualifier globalInputDefaults;
|
||||
TQualifier globalOutputDefaults;
|
||||
TQualifier globalSharedDefaults;
|
||||
TString currentCaller; // name of last function body entered (not valid when at global scope)
|
||||
#ifndef GLSLANG_WEB
|
||||
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
|
||||
bool anyIndexLimits;
|
||||
TIdSetType inductiveLoopIds;
|
||||
TVector<TIntermTyped*> needsIndexLimitationChecking;
|
||||
TStructRecord matrixFixRecord;
|
||||
TStructRecord packingFixRecord;
|
||||
|
||||
//
|
||||
// Geometry shader input arrays:
|
||||
// - array sizing is based on input primitive and/or explicit size
|
||||
//
|
||||
// Tessellation control output arrays:
|
||||
// - array sizing is based on output layout(vertices=...) and/or explicit size
|
||||
//
|
||||
// Both:
|
||||
// - array sizing is retroactive
|
||||
// - built-in block redeclarations interact with this
|
||||
//
|
||||
// Design:
|
||||
// - use a per-context "resize-list", a list of symbols whose array sizes
|
||||
// can be fixed
|
||||
//
|
||||
// - the resize-list starts empty at beginning of user-shader compilation, it does
|
||||
// not have built-ins in it
|
||||
//
|
||||
// - on built-in array use: copyUp() symbol and add it to the resize-list
|
||||
//
|
||||
// - on user array declaration: add it to the resize-list
|
||||
//
|
||||
// - on block redeclaration: copyUp() symbol and add it to the resize-list
|
||||
// * note, that appropriately gives an error if redeclaring a block that
|
||||
// was already used and hence already copied-up
|
||||
//
|
||||
// - on seeing a layout declaration that sizes the array, fix everything in the
|
||||
// resize-list, giving errors for mismatch
|
||||
//
|
||||
// - on seeing an array size declaration, give errors on mismatch between it and previous
|
||||
// array-sizing declarations
|
||||
//
|
||||
TVector<TSymbol*> ioArraySymbolResizeList;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _PARSER_HELPER_INCLUDED_
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace glslang {
|
||||
|
||||
void RemoveAllTreeNodes(TIntermNode*);
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2013 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
#ifndef _GLSLANG_SCAN_INCLUDED_
|
||||
#define _GLSLANG_SCAN_INCLUDED_
|
||||
|
||||
#include "Versions.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// Use a global end-of-input character, so no translation is needed across
|
||||
// layers of encapsulation. Characters are all 8 bit, and positive, so there is
|
||||
// no aliasing of character 255 onto -1, for example.
|
||||
const int EndOfInput = -1;
|
||||
|
||||
//
|
||||
// A character scanner that seamlessly, on read-only strings, reads across an
|
||||
// array of strings without assuming null termination.
|
||||
//
|
||||
class TInputScanner {
|
||||
public:
|
||||
TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr,
|
||||
int b = 0, int f = 0, bool single = false) :
|
||||
numSources(n),
|
||||
// up to this point, common usage is "char*", but now we need positive 8-bit characters
|
||||
sources(reinterpret_cast<const unsigned char* const *>(s)),
|
||||
lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single),
|
||||
endOfFileReached(false)
|
||||
{
|
||||
loc = new TSourceLoc[numSources];
|
||||
for (int i = 0; i < numSources; ++i) {
|
||||
loc[i].init(i - stringBias);
|
||||
}
|
||||
if (names != nullptr) {
|
||||
for (int i = 0; i < numSources; ++i)
|
||||
loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr;
|
||||
}
|
||||
loc[currentSource].line = 1;
|
||||
logicalSourceLoc.init(1);
|
||||
logicalSourceLoc.name = loc[0].name;
|
||||
}
|
||||
|
||||
virtual ~TInputScanner()
|
||||
{
|
||||
delete [] loc;
|
||||
}
|
||||
|
||||
// retrieve the next character and advance one character
|
||||
int get()
|
||||
{
|
||||
int ret = peek();
|
||||
if (ret == EndOfInput)
|
||||
return ret;
|
||||
++loc[currentSource].column;
|
||||
++logicalSourceLoc.column;
|
||||
if (ret == '\n') {
|
||||
++loc[currentSource].line;
|
||||
++logicalSourceLoc.line;
|
||||
logicalSourceLoc.column = 0;
|
||||
loc[currentSource].column = 0;
|
||||
}
|
||||
advance();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// retrieve the next character, no advance
|
||||
int peek()
|
||||
{
|
||||
if (currentSource >= numSources) {
|
||||
endOfFileReached = true;
|
||||
return EndOfInput;
|
||||
}
|
||||
// Make sure we do not read off the end of a string.
|
||||
// N.B. Sources can have a length of 0.
|
||||
int sourceToRead = currentSource;
|
||||
size_t charToRead = currentChar;
|
||||
while(charToRead >= lengths[sourceToRead]) {
|
||||
charToRead = 0;
|
||||
sourceToRead += 1;
|
||||
if (sourceToRead >= numSources) {
|
||||
return EndOfInput;
|
||||
}
|
||||
}
|
||||
|
||||
// Here, we care about making negative valued characters positive
|
||||
return sources[sourceToRead][charToRead];
|
||||
}
|
||||
|
||||
// go back one character
|
||||
void unget()
|
||||
{
|
||||
// Do not roll back once we've reached the end of the file.
|
||||
if (endOfFileReached)
|
||||
return;
|
||||
|
||||
if (currentChar > 0) {
|
||||
--currentChar;
|
||||
--loc[currentSource].column;
|
||||
--logicalSourceLoc.column;
|
||||
if (loc[currentSource].column < 0) {
|
||||
// We've moved back past a new line. Find the
|
||||
// previous newline (or start of the file) to compute
|
||||
// the column count on the now current line.
|
||||
size_t chIndex = currentChar;
|
||||
while (chIndex > 0) {
|
||||
if (sources[currentSource][chIndex] == '\n') {
|
||||
break;
|
||||
}
|
||||
--chIndex;
|
||||
}
|
||||
logicalSourceLoc.column = (int)(currentChar - chIndex);
|
||||
loc[currentSource].column = (int)(currentChar - chIndex);
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
--currentSource;
|
||||
} while (currentSource > 0 && lengths[currentSource] == 0);
|
||||
if (lengths[currentSource] == 0) {
|
||||
// set to 0 if we've backed up to the start of an empty string
|
||||
currentChar = 0;
|
||||
} else
|
||||
currentChar = lengths[currentSource] - 1;
|
||||
}
|
||||
if (peek() == '\n') {
|
||||
--loc[currentSource].line;
|
||||
--logicalSourceLoc.line;
|
||||
}
|
||||
}
|
||||
|
||||
// for #line override
|
||||
void setLine(int newLine)
|
||||
{
|
||||
logicalSourceLoc.line = newLine;
|
||||
loc[getLastValidSourceIndex()].line = newLine;
|
||||
}
|
||||
|
||||
// for #line override in filename based parsing
|
||||
void setFile(const char* filename)
|
||||
{
|
||||
TString* fn_tstr = NewPoolTString(filename);
|
||||
logicalSourceLoc.name = fn_tstr;
|
||||
loc[getLastValidSourceIndex()].name = fn_tstr;
|
||||
}
|
||||
|
||||
void setFile(const char* filename, int i)
|
||||
{
|
||||
TString* fn_tstr = NewPoolTString(filename);
|
||||
if (i == getLastValidSourceIndex()) {
|
||||
logicalSourceLoc.name = fn_tstr;
|
||||
}
|
||||
loc[i].name = fn_tstr;
|
||||
}
|
||||
|
||||
void setString(int newString)
|
||||
{
|
||||
logicalSourceLoc.string = newString;
|
||||
loc[getLastValidSourceIndex()].string = newString;
|
||||
logicalSourceLoc.name = nullptr;
|
||||
loc[getLastValidSourceIndex()].name = nullptr;
|
||||
}
|
||||
|
||||
// for #include content indentation
|
||||
void setColumn(int col)
|
||||
{
|
||||
logicalSourceLoc.column = col;
|
||||
loc[getLastValidSourceIndex()].column = col;
|
||||
}
|
||||
|
||||
void setEndOfInput()
|
||||
{
|
||||
endOfFileReached = true;
|
||||
currentSource = numSources;
|
||||
}
|
||||
|
||||
bool atEndOfInput() const { return endOfFileReached; }
|
||||
|
||||
const TSourceLoc& getSourceLoc() const
|
||||
{
|
||||
if (singleLogical) {
|
||||
return logicalSourceLoc;
|
||||
} else {
|
||||
return loc[std::max(0, std::min(currentSource, numSources - finale - 1))];
|
||||
}
|
||||
}
|
||||
// Returns the index (starting from 0) of the most recent valid source string we are reading from.
|
||||
int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); }
|
||||
|
||||
void consumeWhiteSpace(bool& foundNonSpaceTab);
|
||||
bool consumeComment();
|
||||
void consumeWhitespaceComment(bool& foundNonSpaceTab);
|
||||
bool scanVersion(int& version, EProfile& profile, bool& notFirstToken);
|
||||
|
||||
protected:
|
||||
|
||||
// advance one character
|
||||
void advance()
|
||||
{
|
||||
++currentChar;
|
||||
if (currentChar >= lengths[currentSource]) {
|
||||
++currentSource;
|
||||
if (currentSource < numSources) {
|
||||
loc[currentSource].string = loc[currentSource - 1].string + 1;
|
||||
loc[currentSource].line = 1;
|
||||
loc[currentSource].column = 0;
|
||||
}
|
||||
while (currentSource < numSources && lengths[currentSource] == 0) {
|
||||
++currentSource;
|
||||
if (currentSource < numSources) {
|
||||
loc[currentSource].string = loc[currentSource - 1].string + 1;
|
||||
loc[currentSource].line = 1;
|
||||
loc[currentSource].column = 0;
|
||||
}
|
||||
}
|
||||
currentChar = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int numSources; // number of strings in source
|
||||
const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput
|
||||
const size_t *lengths; // length of each string
|
||||
int currentSource;
|
||||
size_t currentChar;
|
||||
|
||||
// This is for reporting what string/line an error occurred on, and can be overridden by #line.
|
||||
// It remembers the last state of each source string as it is left for the next one, so unget()
|
||||
// can restore that state.
|
||||
TSourceLoc* loc; // an array
|
||||
|
||||
int stringBias; // the first string that is the user's string number 0
|
||||
int finale; // number of internal strings after user's last string
|
||||
|
||||
TSourceLoc logicalSourceLoc;
|
||||
bool singleLogical; // treats the strings as a single logical string.
|
||||
// locations will be reported from the first string.
|
||||
|
||||
// Set to true once peek() returns EndOfFile, so that we won't roll back
|
||||
// once we've reached EndOfFile.
|
||||
bool endOfFileReached;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _GLSLANG_SCAN_INCLUDED_
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// Copyright (C) 2013 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
//
|
||||
// This holds context specific to the GLSL scanner, which
|
||||
// sits between the preprocessor scanner and parser.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ParseHelper.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TPpContext;
|
||||
class TPpToken;
|
||||
class TParserToken;
|
||||
|
||||
class TScanContext {
|
||||
public:
|
||||
explicit TScanContext(TParseContextBase& pc) :
|
||||
parseContext(pc),
|
||||
afterType(false), afterStruct(false),
|
||||
field(false), afterBuffer(false) { }
|
||||
virtual ~TScanContext() { }
|
||||
|
||||
static void fillInKeywordMap();
|
||||
static void deleteKeywordMap();
|
||||
|
||||
int tokenize(TPpContext*, TParserToken&);
|
||||
|
||||
protected:
|
||||
TScanContext(TScanContext&);
|
||||
TScanContext& operator=(TScanContext&);
|
||||
|
||||
int tokenizeIdentifier();
|
||||
int identifierOrType();
|
||||
int reservedWord();
|
||||
int identifierOrReserved(bool reserved);
|
||||
int es30ReservedFromGLSL(int version);
|
||||
int nonreservedKeyword(int esVersion, int nonEsVersion);
|
||||
int precisionKeyword();
|
||||
int matNxM();
|
||||
int dMat();
|
||||
int firstGenerationImage(bool inEs310);
|
||||
int secondGenerationImage();
|
||||
|
||||
TParseContextBase& parseContext;
|
||||
bool afterType; // true if we've recognized a type, so can only be looking for an identifier
|
||||
bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier
|
||||
bool field; // true if we're on a field, right after a '.'
|
||||
bool afterBuffer; // true if we've recognized the BUFFER keyword
|
||||
TSourceLoc loc;
|
||||
TParserToken* parserToken;
|
||||
TPpToken* ppToken;
|
||||
|
||||
const char* tokenText;
|
||||
int keyword;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
@ -0,0 +1,917 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2013 LunarG, Inc.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _SYMBOL_TABLE_INCLUDED_
|
||||
#define _SYMBOL_TABLE_INCLUDED_
|
||||
|
||||
//
|
||||
// Symbol table for parsing. Has these design characteristics:
|
||||
//
|
||||
// * Same symbol table can be used to compile many shaders, to preserve
|
||||
// effort of creating and loading with the large numbers of built-in
|
||||
// symbols.
|
||||
//
|
||||
// --> This requires a copy mechanism, so initial pools used to create
|
||||
// the shared information can be popped. Done through "clone"
|
||||
// methods.
|
||||
//
|
||||
// * Name mangling will be used to give each function a unique name
|
||||
// so that symbol table lookups are never ambiguous. This allows
|
||||
// a simpler symbol table structure.
|
||||
//
|
||||
// * Pushing and popping of scope, so symbol table will really be a stack
|
||||
// of symbol tables. Searched from the top, with new inserts going into
|
||||
// the top.
|
||||
//
|
||||
// * Constants: Compile time constant symbols will keep their values
|
||||
// in the symbol table. The parser can substitute constants at parse
|
||||
// time, including doing constant folding and constant propagation.
|
||||
//
|
||||
// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
|
||||
// are tracked in the intermediate representation, not the symbol table.
|
||||
//
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include "../Include/intermediate.h"
|
||||
#include "../Include/InfoSink.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// Symbol base class. (Can build functions or variables out of these...)
|
||||
//
|
||||
|
||||
class TVariable;
|
||||
class TFunction;
|
||||
class TAnonMember;
|
||||
|
||||
typedef TVector<const char*> TExtensionList;
|
||||
|
||||
class TSymbol {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
|
||||
virtual TSymbol* clone() const = 0;
|
||||
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
|
||||
|
||||
virtual const TString& getName() const { return *name; }
|
||||
virtual void changeName(const TString* newName) { name = newName; }
|
||||
virtual void addPrefix(const char* prefix)
|
||||
{
|
||||
TString newName(prefix);
|
||||
newName.append(*name);
|
||||
changeName(NewPoolTString(newName.c_str()));
|
||||
}
|
||||
virtual const TString& getMangledName() const { return getName(); }
|
||||
virtual TFunction* getAsFunction() { return 0; }
|
||||
virtual const TFunction* getAsFunction() const { return 0; }
|
||||
virtual TVariable* getAsVariable() { return 0; }
|
||||
virtual const TVariable* getAsVariable() const { return 0; }
|
||||
virtual const TAnonMember* getAsAnonMember() const { return 0; }
|
||||
virtual const TType& getType() const = 0;
|
||||
virtual TType& getWritableType() = 0;
|
||||
virtual void setUniqueId(long long id) { uniqueId = id; }
|
||||
virtual long long getUniqueId() const { return uniqueId; }
|
||||
virtual void setExtensions(int numExts, const char* const exts[])
|
||||
{
|
||||
assert(extensions == 0);
|
||||
assert(numExts > 0);
|
||||
extensions = NewPoolObject(extensions);
|
||||
for (int e = 0; e < numExts; ++e)
|
||||
extensions->push_back(exts[e]);
|
||||
}
|
||||
virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
|
||||
virtual const char** getExtensions() const { return extensions->data(); }
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
|
||||
void dumpExtensions(TInfoSink& infoSink) const;
|
||||
#endif
|
||||
|
||||
virtual bool isReadOnly() const { return ! writable; }
|
||||
virtual void makeReadOnly() { writable = false; }
|
||||
|
||||
protected:
|
||||
explicit TSymbol(const TSymbol&);
|
||||
TSymbol& operator=(const TSymbol&);
|
||||
|
||||
const TString *name;
|
||||
unsigned long long uniqueId; // For cross-scope comparing during code generation
|
||||
|
||||
// For tracking what extensions must be present
|
||||
// (don't use if correct version/profile is present).
|
||||
TExtensionList* extensions; // an array of pointers to existing constant char strings
|
||||
|
||||
//
|
||||
// N.B.: Non-const functions that will be generally used should assert on this,
|
||||
// to avoid overwriting shared symbol-table information.
|
||||
//
|
||||
bool writable;
|
||||
};
|
||||
|
||||
//
|
||||
// Variable class, meaning a symbol that's not a function.
|
||||
//
|
||||
// There could be a separate class hierarchy for Constant variables;
|
||||
// Only one of int, bool, or float, (or none) is correct for
|
||||
// any particular use, but it's easy to do this way, and doesn't
|
||||
// seem worth having separate classes, and "getConst" can't simply return
|
||||
// different values for different types polymorphically, so this is
|
||||
// just simple and pragmatic.
|
||||
//
|
||||
class TVariable : public TSymbol {
|
||||
public:
|
||||
TVariable(const TString *name, const TType& t, bool uT = false )
|
||||
: TSymbol(name),
|
||||
userType(uT),
|
||||
constSubtree(nullptr),
|
||||
memberExtensions(nullptr),
|
||||
anonId(-1)
|
||||
{ type.shallowCopy(t); }
|
||||
virtual TVariable* clone() const;
|
||||
virtual ~TVariable() { }
|
||||
|
||||
virtual TVariable* getAsVariable() { return this; }
|
||||
virtual const TVariable* getAsVariable() const { return this; }
|
||||
virtual const TType& getType() const { return type; }
|
||||
virtual TType& getWritableType() { assert(writable); return type; }
|
||||
virtual bool isUserType() const { return userType; }
|
||||
virtual const TConstUnionArray& getConstArray() const { return constArray; }
|
||||
virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
|
||||
virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
|
||||
virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
|
||||
virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
|
||||
virtual void setAnonId(int i) { anonId = i; }
|
||||
virtual int getAnonId() const { return anonId; }
|
||||
|
||||
virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
|
||||
{
|
||||
assert(type.isStruct());
|
||||
assert(numExts > 0);
|
||||
if (memberExtensions == nullptr) {
|
||||
memberExtensions = NewPoolObject(memberExtensions);
|
||||
memberExtensions->resize(type.getStruct()->size());
|
||||
}
|
||||
for (int e = 0; e < numExts; ++e)
|
||||
(*memberExtensions)[member].push_back(exts[e]);
|
||||
}
|
||||
virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
|
||||
virtual int getNumMemberExtensions(int member) const
|
||||
{
|
||||
return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
|
||||
}
|
||||
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
explicit TVariable(const TVariable&);
|
||||
TVariable& operator=(const TVariable&);
|
||||
|
||||
TType type;
|
||||
bool userType;
|
||||
|
||||
// we are assuming that Pool Allocator will free the memory allocated to unionArray
|
||||
// when this object is destroyed
|
||||
|
||||
TConstUnionArray constArray; // for compile-time constant value
|
||||
TIntermTyped* constSubtree; // for specialization constant computation
|
||||
TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
|
||||
int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
|
||||
};
|
||||
|
||||
//
|
||||
// The function sub-class of symbols and the parser will need to
|
||||
// share this definition of a function parameter.
|
||||
//
|
||||
struct TParameter {
|
||||
TString *name;
|
||||
TType* type;
|
||||
TIntermTyped* defaultValue;
|
||||
void copyParam(const TParameter& param)
|
||||
{
|
||||
if (param.name)
|
||||
name = NewPoolTString(param.name->c_str());
|
||||
else
|
||||
name = 0;
|
||||
type = param.type->clone();
|
||||
defaultValue = param.defaultValue;
|
||||
}
|
||||
TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
|
||||
};
|
||||
|
||||
//
|
||||
// The function sub-class of a symbol.
|
||||
//
|
||||
class TFunction : public TSymbol {
|
||||
public:
|
||||
explicit TFunction(TOperator o) :
|
||||
TSymbol(0),
|
||||
op(o),
|
||||
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
|
||||
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
|
||||
TSymbol(name),
|
||||
mangledName(*name + '('),
|
||||
op(tOp),
|
||||
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
|
||||
{
|
||||
returnType.shallowCopy(retType);
|
||||
declaredBuiltIn = retType.getQualifier().builtIn;
|
||||
}
|
||||
virtual TFunction* clone() const override;
|
||||
virtual ~TFunction();
|
||||
|
||||
virtual TFunction* getAsFunction() override { return this; }
|
||||
virtual const TFunction* getAsFunction() const override { return this; }
|
||||
|
||||
// Install 'p' as the (non-'this') last parameter.
|
||||
// Non-'this' parameters are reflected in both the list of parameters and the
|
||||
// mangled name.
|
||||
virtual void addParameter(TParameter& p)
|
||||
{
|
||||
assert(writable);
|
||||
parameters.push_back(p);
|
||||
p.type->appendMangledName(mangledName);
|
||||
|
||||
if (p.defaultValue != nullptr)
|
||||
defaultParamCount++;
|
||||
}
|
||||
|
||||
// Install 'this' as the first parameter.
|
||||
// 'this' is reflected in the list of parameters, but not the mangled name.
|
||||
virtual void addThisParameter(TType& type, const char* name)
|
||||
{
|
||||
TParameter p = { NewPoolTString(name), new TType, nullptr };
|
||||
p.type->shallowCopy(type);
|
||||
parameters.insert(parameters.begin(), p);
|
||||
}
|
||||
|
||||
virtual void addPrefix(const char* prefix) override
|
||||
{
|
||||
TSymbol::addPrefix(prefix);
|
||||
mangledName.insert(0, prefix);
|
||||
}
|
||||
|
||||
virtual void removePrefix(const TString& prefix)
|
||||
{
|
||||
assert(mangledName.compare(0, prefix.size(), prefix) == 0);
|
||||
mangledName.erase(0, prefix.size());
|
||||
}
|
||||
|
||||
virtual const TString& getMangledName() const override { return mangledName; }
|
||||
virtual const TType& getType() const override { return returnType; }
|
||||
virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
|
||||
virtual TType& getWritableType() override { return returnType; }
|
||||
virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
|
||||
virtual TOperator getBuiltInOp() const { return op; }
|
||||
virtual void setDefined() { assert(writable); defined = true; }
|
||||
virtual bool isDefined() const { return defined; }
|
||||
virtual void setPrototyped() { assert(writable); prototyped = true; }
|
||||
virtual bool isPrototyped() const { return prototyped; }
|
||||
virtual void setImplicitThis() { assert(writable); implicitThis = true; }
|
||||
virtual bool hasImplicitThis() const { return implicitThis; }
|
||||
virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
|
||||
virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
|
||||
|
||||
// Return total number of parameters
|
||||
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
|
||||
// Return number of parameters with default values.
|
||||
virtual int getDefaultParamCount() const { return defaultParamCount; }
|
||||
// Return number of fixed parameters (without default values)
|
||||
virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
|
||||
|
||||
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
|
||||
virtual const TParameter& operator[](int i) const { return parameters[i]; }
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
explicit TFunction(const TFunction&);
|
||||
TFunction& operator=(const TFunction&);
|
||||
|
||||
typedef TVector<TParameter> TParamList;
|
||||
TParamList parameters;
|
||||
TType returnType;
|
||||
TBuiltInVariable declaredBuiltIn;
|
||||
|
||||
TString mangledName;
|
||||
TOperator op;
|
||||
bool defined;
|
||||
bool prototyped;
|
||||
bool implicitThis; // True if this function is allowed to see all members of 'this'
|
||||
bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this',
|
||||
// even if it finds member variables in the symbol table.
|
||||
// This is important for a static member function that has member variables in scope,
|
||||
// but is not allowed to use them, or see hidden symbols instead.
|
||||
int defaultParamCount;
|
||||
};
|
||||
|
||||
//
|
||||
// Members of anonymous blocks are a kind of TSymbol. They are not hidden in
|
||||
// the symbol table behind a container; rather they are visible and point to
|
||||
// their anonymous container. (The anonymous container is found through the
|
||||
// member, not the other way around.)
|
||||
//
|
||||
class TAnonMember : public TSymbol {
|
||||
public:
|
||||
TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
|
||||
virtual TAnonMember* clone() const override;
|
||||
virtual ~TAnonMember() { }
|
||||
|
||||
virtual const TAnonMember* getAsAnonMember() const override { return this; }
|
||||
virtual const TVariable& getAnonContainer() const { return anonContainer; }
|
||||
virtual unsigned int getMemberNumber() const { return memberNumber; }
|
||||
|
||||
virtual const TType& getType() const override
|
||||
{
|
||||
const TTypeList& types = *anonContainer.getType().getStruct();
|
||||
return *types[memberNumber].type;
|
||||
}
|
||||
|
||||
virtual TType& getWritableType() override
|
||||
{
|
||||
assert(writable);
|
||||
const TTypeList& types = *anonContainer.getType().getStruct();
|
||||
return *types[memberNumber].type;
|
||||
}
|
||||
|
||||
virtual void setExtensions(int numExts, const char* const exts[]) override
|
||||
{
|
||||
anonContainer.setMemberExtensions(memberNumber, numExts, exts);
|
||||
}
|
||||
virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
|
||||
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
|
||||
|
||||
virtual int getAnonId() const { return anonId; }
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
explicit TAnonMember(const TAnonMember&);
|
||||
TAnonMember& operator=(const TAnonMember&);
|
||||
|
||||
TVariable& anonContainer;
|
||||
unsigned int memberNumber;
|
||||
int anonId;
|
||||
};
|
||||
|
||||
class TSymbolTableLevel {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
|
||||
~TSymbolTableLevel();
|
||||
|
||||
bool insert(TSymbol& symbol, bool separateNameSpaces)
|
||||
{
|
||||
//
|
||||
// returning true means symbol was added to the table with no semantic errors
|
||||
//
|
||||
const TString& name = symbol.getName();
|
||||
if (name == "") {
|
||||
symbol.getAsVariable()->setAnonId(anonId++);
|
||||
// An empty name means an anonymous container, exposing its members to the external scope.
|
||||
// Give it a name and insert its members in the symbol table, pointing to the container.
|
||||
char buf[20];
|
||||
snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId());
|
||||
symbol.changeName(NewPoolTString(buf));
|
||||
|
||||
return insertAnonymousMembers(symbol, 0);
|
||||
} else {
|
||||
// Check for redefinition errors:
|
||||
// - STL itself will tell us if there is a direct name collision, with name mangling, at this level
|
||||
// - additionally, check for function-redefining-variable name collisions
|
||||
const TString& insertName = symbol.getMangledName();
|
||||
if (symbol.getAsFunction()) {
|
||||
// make sure there isn't a variable of this name
|
||||
if (! separateNameSpaces && level.find(name) != level.end())
|
||||
return false;
|
||||
|
||||
// insert, and whatever happens is okay
|
||||
level.insert(tLevelPair(insertName, &symbol));
|
||||
|
||||
return true;
|
||||
} else
|
||||
return level.insert(tLevelPair(insertName, &symbol)).second;
|
||||
}
|
||||
}
|
||||
|
||||
// Add more members to an already inserted aggregate object
|
||||
bool amend(TSymbol& symbol, int firstNewMember)
|
||||
{
|
||||
// See insert() for comments on basic explanation of insert.
|
||||
// This operates similarly, but more simply.
|
||||
// Only supporting amend of anonymous blocks so far.
|
||||
if (IsAnonymous(symbol.getName()))
|
||||
return insertAnonymousMembers(symbol, firstNewMember);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool insertAnonymousMembers(TSymbol& symbol, int firstMember)
|
||||
{
|
||||
const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
|
||||
for (unsigned int m = firstMember; m < types.size(); ++m) {
|
||||
TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId());
|
||||
if (! level.insert(tLevelPair(member->getMangledName(), member)).second)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TSymbol* find(const TString& name) const
|
||||
{
|
||||
tLevel::const_iterator it = level.find(name);
|
||||
if (it == level.end())
|
||||
return 0;
|
||||
else
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
void findFunctionNameList(const TString& name, TVector<const TFunction*>& list)
|
||||
{
|
||||
size_t parenAt = name.find_first_of('(');
|
||||
TString base(name, 0, parenAt + 1);
|
||||
|
||||
tLevel::const_iterator begin = level.lower_bound(base);
|
||||
base[parenAt] = ')'; // assume ')' is lexically after '('
|
||||
tLevel::const_iterator end = level.upper_bound(base);
|
||||
for (tLevel::const_iterator it = begin; it != end; ++it)
|
||||
list.push_back(it->second->getAsFunction());
|
||||
}
|
||||
|
||||
// See if there is already a function in the table having the given non-function-style name.
|
||||
bool hasFunctionName(const TString& name) const
|
||||
{
|
||||
tLevel::const_iterator candidate = level.lower_bound(name);
|
||||
if (candidate != level.end()) {
|
||||
const TString& candidateName = (*candidate).first;
|
||||
TString::size_type parenAt = candidateName.find_first_of('(');
|
||||
if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// See if there is a variable at this level having the given non-function-style name.
|
||||
// Return true if name is found, and set variable to true if the name was a variable.
|
||||
bool findFunctionVariableName(const TString& name, bool& variable) const
|
||||
{
|
||||
tLevel::const_iterator candidate = level.lower_bound(name);
|
||||
if (candidate != level.end()) {
|
||||
const TString& candidateName = (*candidate).first;
|
||||
TString::size_type parenAt = candidateName.find_first_of('(');
|
||||
if (parenAt == candidateName.npos) {
|
||||
// not a mangled name
|
||||
if (candidateName == name) {
|
||||
// found a variable name match
|
||||
variable = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// a mangled name
|
||||
if (candidateName.compare(0, parenAt, name) == 0) {
|
||||
// found a function name match
|
||||
variable = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use this to do a lazy 'push' of precision defaults the first time
|
||||
// a precision statement is seen in a new scope. Leave it at 0 for
|
||||
// when no push was needed. Thus, it is not the current defaults,
|
||||
// it is what to restore the defaults to when popping a level.
|
||||
void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
|
||||
{
|
||||
// can call multiple times at one scope, will only latch on first call,
|
||||
// as we're tracking the previous scope's values, not the current values
|
||||
if (defaultPrecision != 0)
|
||||
return;
|
||||
|
||||
defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
|
||||
for (int t = 0; t < EbtNumTypes; ++t)
|
||||
defaultPrecision[t] = p[t];
|
||||
}
|
||||
|
||||
void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
|
||||
{
|
||||
// can be called for table level pops that didn't set the
|
||||
// defaults
|
||||
if (defaultPrecision == 0 || p == 0)
|
||||
return;
|
||||
|
||||
for (int t = 0; t < EbtNumTypes; ++t)
|
||||
p[t] = defaultPrecision[t];
|
||||
}
|
||||
|
||||
void relateToOperator(const char* name, TOperator op);
|
||||
void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
void dump(TInfoSink& infoSink, bool complete = false) const;
|
||||
#endif
|
||||
TSymbolTableLevel* clone() const;
|
||||
void readOnly();
|
||||
|
||||
void setThisLevel() { thisLevel = true; }
|
||||
bool isThisLevel() const { return thisLevel; }
|
||||
|
||||
protected:
|
||||
explicit TSymbolTableLevel(TSymbolTableLevel&);
|
||||
TSymbolTableLevel& operator=(TSymbolTableLevel&);
|
||||
|
||||
typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
|
||||
typedef const tLevel::value_type tLevelPair;
|
||||
typedef std::pair<tLevel::iterator, bool> tInsertResult;
|
||||
|
||||
tLevel level; // named mappings
|
||||
TPrecisionQualifier *defaultPrecision;
|
||||
int anonId;
|
||||
bool thisLevel; // True if this level of the symbol table is a structure scope containing member function
|
||||
// that are supposed to see anonymous access to member variables.
|
||||
};
|
||||
|
||||
class TSymbolTable {
|
||||
public:
|
||||
TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0)
|
||||
{
|
||||
//
|
||||
// This symbol table cannot be used until push() is called.
|
||||
//
|
||||
}
|
||||
~TSymbolTable()
|
||||
{
|
||||
// this can be called explicitly; safest to code it so it can be called multiple times
|
||||
|
||||
// don't deallocate levels passed in from elsewhere
|
||||
while (table.size() > adoptedLevels)
|
||||
pop(0);
|
||||
}
|
||||
|
||||
void adoptLevels(TSymbolTable& symTable)
|
||||
{
|
||||
for (unsigned int level = 0; level < symTable.table.size(); ++level) {
|
||||
table.push_back(symTable.table[level]);
|
||||
++adoptedLevels;
|
||||
}
|
||||
uniqueId = symTable.uniqueId;
|
||||
noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
|
||||
separateNameSpaces = symTable.separateNameSpaces;
|
||||
}
|
||||
|
||||
//
|
||||
// While level adopting is generic, the methods below enact a the following
|
||||
// convention for levels:
|
||||
// 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
|
||||
// 1: per-stage built-ins, shared across all compiles, but a different copy per stage
|
||||
// 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins
|
||||
// 3: user-shader globals
|
||||
//
|
||||
protected:
|
||||
static const uint32_t LevelFlagBitOffset = 56;
|
||||
static const int globalLevel = 3;
|
||||
static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
|
||||
static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
|
||||
static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
|
||||
public:
|
||||
bool isEmpty() { return table.size() == 0; }
|
||||
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
|
||||
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
|
||||
static bool isBuiltInSymbol(long long uniqueId) {
|
||||
int level = static_cast<int>(uniqueId >> LevelFlagBitOffset);
|
||||
return isBuiltInLevel(level);
|
||||
}
|
||||
static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1;
|
||||
static const uint32_t MaxLevelInUniqueID = 127;
|
||||
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
|
||||
void setSeparateNameSpaces() { separateNameSpaces = true; }
|
||||
|
||||
void push()
|
||||
{
|
||||
table.push_back(new TSymbolTableLevel);
|
||||
updateUniqueIdLevelFlag();
|
||||
}
|
||||
|
||||
// Make a new symbol-table level to represent the scope introduced by a structure
|
||||
// containing member functions, such that the member functions can find anonymous
|
||||
// references to member variables.
|
||||
//
|
||||
// 'thisSymbol' should have a name of "" to trigger anonymous structure-member
|
||||
// symbol finds.
|
||||
void pushThis(TSymbol& thisSymbol)
|
||||
{
|
||||
assert(thisSymbol.getName().size() == 0);
|
||||
table.push_back(new TSymbolTableLevel);
|
||||
updateUniqueIdLevelFlag();
|
||||
table.back()->setThisLevel();
|
||||
insert(thisSymbol);
|
||||
}
|
||||
|
||||
void pop(TPrecisionQualifier *p)
|
||||
{
|
||||
table[currentLevel()]->getPreviousDefaultPrecisions(p);
|
||||
delete table.back();
|
||||
table.pop_back();
|
||||
updateUniqueIdLevelFlag();
|
||||
}
|
||||
|
||||
//
|
||||
// Insert a visible symbol into the symbol table so it can
|
||||
// be found later by name.
|
||||
//
|
||||
// Returns false if the was a name collision.
|
||||
//
|
||||
bool insert(TSymbol& symbol)
|
||||
{
|
||||
symbol.setUniqueId(++uniqueId);
|
||||
|
||||
// make sure there isn't a function of this variable name
|
||||
if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName()))
|
||||
return false;
|
||||
|
||||
// check for not overloading or redefining a built-in function
|
||||
if (noBuiltInRedeclarations) {
|
||||
if (atGlobalLevel() && currentLevel() > 0) {
|
||||
if (table[0]->hasFunctionName(symbol.getName()))
|
||||
return false;
|
||||
if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return table[currentLevel()]->insert(symbol, separateNameSpaces);
|
||||
}
|
||||
|
||||
// Add more members to an already inserted aggregate object
|
||||
bool amend(TSymbol& symbol, int firstNewMember)
|
||||
{
|
||||
// See insert() for comments on basic explanation of insert.
|
||||
// This operates similarly, but more simply.
|
||||
return table[currentLevel()]->amend(symbol, firstNewMember);
|
||||
}
|
||||
|
||||
// Update the level info in symbol's unique ID to current level
|
||||
void amendSymbolIdLevel(TSymbol& symbol)
|
||||
{
|
||||
// clamp level to avoid overflow
|
||||
uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
|
||||
uint64_t symbolId = symbol.getUniqueId();
|
||||
symbolId &= uniqueIdMask;
|
||||
symbolId |= (level << LevelFlagBitOffset);
|
||||
symbol.setUniqueId(symbolId);
|
||||
}
|
||||
//
|
||||
// To allocate an internal temporary, which will need to be uniquely
|
||||
// identified by the consumer of the AST, but never need to
|
||||
// found by doing a symbol table search by name, hence allowed an
|
||||
// arbitrary name in the symbol with no worry of collision.
|
||||
//
|
||||
void makeInternalVariable(TSymbol& symbol)
|
||||
{
|
||||
symbol.setUniqueId(++uniqueId);
|
||||
}
|
||||
|
||||
//
|
||||
// Copy a variable or anonymous member's structure from a shared level so that
|
||||
// it can be added (soon after return) to the symbol table where it can be
|
||||
// modified without impacting other users of the shared table.
|
||||
//
|
||||
TSymbol* copyUpDeferredInsert(TSymbol* shared)
|
||||
{
|
||||
if (shared->getAsVariable()) {
|
||||
TSymbol* copy = shared->clone();
|
||||
copy->setUniqueId(shared->getUniqueId());
|
||||
return copy;
|
||||
} else {
|
||||
const TAnonMember* anon = shared->getAsAnonMember();
|
||||
assert(anon);
|
||||
TVariable* container = anon->getAnonContainer().clone();
|
||||
container->changeName(NewPoolTString(""));
|
||||
container->setUniqueId(anon->getAnonContainer().getUniqueId());
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
TSymbol* copyUp(TSymbol* shared)
|
||||
{
|
||||
TSymbol* copy = copyUpDeferredInsert(shared);
|
||||
table[globalLevel]->insert(*copy, separateNameSpaces);
|
||||
if (shared->getAsVariable())
|
||||
return copy;
|
||||
else {
|
||||
// return the copy of the anonymous member
|
||||
return table[globalLevel]->find(shared->getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Normal find of a symbol, that can optionally say whether the symbol was found
|
||||
// at a built-in level or the current top-scope level.
|
||||
TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
|
||||
{
|
||||
int level = currentLevel();
|
||||
TSymbol* symbol;
|
||||
int thisDepth = 0;
|
||||
do {
|
||||
if (table[level]->isThisLevel())
|
||||
++thisDepth;
|
||||
symbol = table[level]->find(name);
|
||||
--level;
|
||||
} while (symbol == nullptr && level >= 0);
|
||||
level++;
|
||||
if (builtIn)
|
||||
*builtIn = isBuiltInLevel(level);
|
||||
if (currentScope)
|
||||
*currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals
|
||||
if (thisDepthP != nullptr) {
|
||||
if (! table[level]->isThisLevel())
|
||||
thisDepth = 0;
|
||||
*thisDepthP = thisDepth;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
// Find of a symbol that returns how many layers deep of nested
|
||||
// structures-with-member-functions ('this' scopes) deep the symbol was
|
||||
// found in.
|
||||
TSymbol* find(const TString& name, int& thisDepth)
|
||||
{
|
||||
int level = currentLevel();
|
||||
TSymbol* symbol;
|
||||
thisDepth = 0;
|
||||
do {
|
||||
if (table[level]->isThisLevel())
|
||||
++thisDepth;
|
||||
symbol = table[level]->find(name);
|
||||
--level;
|
||||
} while (symbol == 0 && level >= 0);
|
||||
|
||||
if (! table[level + 1]->isThisLevel())
|
||||
thisDepth = 0;
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
bool isFunctionNameVariable(const TString& name) const
|
||||
{
|
||||
if (separateNameSpaces)
|
||||
return false;
|
||||
|
||||
int level = currentLevel();
|
||||
do {
|
||||
bool variable;
|
||||
bool found = table[level]->findFunctionVariableName(name, variable);
|
||||
if (found)
|
||||
return variable;
|
||||
--level;
|
||||
} while (level >= 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void findFunctionNameList(const TString& name, TVector<const TFunction*>& list, bool& builtIn)
|
||||
{
|
||||
// For user levels, return the set found in the first scope with a match
|
||||
builtIn = false;
|
||||
int level = currentLevel();
|
||||
do {
|
||||
table[level]->findFunctionNameList(name, list);
|
||||
--level;
|
||||
} while (list.empty() && level >= globalLevel);
|
||||
|
||||
if (! list.empty())
|
||||
return;
|
||||
|
||||
// Gather across all built-in levels; they don't hide each other
|
||||
builtIn = true;
|
||||
do {
|
||||
table[level]->findFunctionNameList(name, list);
|
||||
--level;
|
||||
} while (level >= 0);
|
||||
}
|
||||
|
||||
void relateToOperator(const char* name, TOperator op)
|
||||
{
|
||||
for (unsigned int level = 0; level < table.size(); ++level)
|
||||
table[level]->relateToOperator(name, op);
|
||||
}
|
||||
|
||||
void setFunctionExtensions(const char* name, int num, const char* const extensions[])
|
||||
{
|
||||
for (unsigned int level = 0; level < table.size(); ++level)
|
||||
table[level]->setFunctionExtensions(name, num, extensions);
|
||||
}
|
||||
|
||||
void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
|
||||
{
|
||||
TSymbol* symbol = find(TString(name));
|
||||
if (symbol == nullptr)
|
||||
return;
|
||||
|
||||
symbol->setExtensions(numExts, extensions);
|
||||
}
|
||||
|
||||
void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
|
||||
{
|
||||
TSymbol* symbol = find(TString(blockName));
|
||||
if (symbol == nullptr)
|
||||
return;
|
||||
TVariable* variable = symbol->getAsVariable();
|
||||
assert(variable != nullptr);
|
||||
|
||||
const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
|
||||
for (int member = 0; member < (int)structure.size(); ++member) {
|
||||
if (structure[member].type->getFieldName().compare(name) == 0) {
|
||||
variable->setMemberExtensions(member, numExts, extensions);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long long getMaxSymbolId() { return uniqueId; }
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
void dump(TInfoSink& infoSink, bool complete = false) const;
|
||||
#endif
|
||||
void copyTable(const TSymbolTable& copyOf);
|
||||
|
||||
void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
|
||||
|
||||
void readOnly()
|
||||
{
|
||||
for (unsigned int level = 0; level < table.size(); ++level)
|
||||
table[level]->readOnly();
|
||||
}
|
||||
|
||||
// Add current level in the high-bits of unique id
|
||||
void updateUniqueIdLevelFlag() {
|
||||
// clamp level to avoid overflow
|
||||
uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
|
||||
uniqueId &= uniqueIdMask;
|
||||
uniqueId |= (level << LevelFlagBitOffset);
|
||||
}
|
||||
|
||||
void overwriteUniqueId(long long id)
|
||||
{
|
||||
uniqueId = id;
|
||||
updateUniqueIdLevelFlag();
|
||||
}
|
||||
|
||||
protected:
|
||||
TSymbolTable(TSymbolTable&);
|
||||
TSymbolTable& operator=(TSymbolTableLevel&);
|
||||
|
||||
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
||||
std::vector<TSymbolTableLevel*> table;
|
||||
long long uniqueId; // for unique identification in code generation
|
||||
bool noBuiltInRedeclarations;
|
||||
bool separateNameSpaces;
|
||||
unsigned int adoptedLevels;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _SYMBOL_TABLE_INCLUDED_
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
||||
// Copyright (C) 2017 ARM Limited.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _VERSIONS_INCLUDED_
|
||||
#define _VERSIONS_INCLUDED_
|
||||
|
||||
#define LAST_ELEMENT_MARKER(x) x
|
||||
|
||||
//
|
||||
// Help manage multiple profiles, versions, extensions etc.
|
||||
//
|
||||
|
||||
//
|
||||
// Profiles are set up for masking operations, so queries can be done on multiple
|
||||
// profiles at the same time.
|
||||
//
|
||||
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
|
||||
// defects from mixing the two different forms.
|
||||
//
|
||||
typedef enum : unsigned {
|
||||
EBadProfile = 0,
|
||||
ENoProfile = (1 << 0), // only for desktop, before profiles showed up
|
||||
ECoreProfile = (1 << 1),
|
||||
ECompatibilityProfile = (1 << 2),
|
||||
EEsProfile = (1 << 3),
|
||||
LAST_ELEMENT_MARKER(EProfileCount),
|
||||
} EProfile;
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// Map from profile enum to externally readable text name.
|
||||
//
|
||||
inline const char* ProfileName(EProfile profile)
|
||||
{
|
||||
switch (profile) {
|
||||
case ENoProfile: return "none";
|
||||
case ECoreProfile: return "core";
|
||||
case ECompatibilityProfile: return "compatibility";
|
||||
case EEsProfile: return "es";
|
||||
default: return "unknown profile";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// What source rules, validation rules, target language, etc. are needed or
|
||||
// desired for SPIR-V?
|
||||
//
|
||||
// 0 means a target or rule set is not enabled (ignore rules from that entity).
|
||||
// Non-0 means to apply semantic rules arising from that version of its rule set.
|
||||
// The union of all requested rule sets will be applied.
|
||||
//
|
||||
struct SpvVersion {
|
||||
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {}
|
||||
unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
|
||||
int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
|
||||
int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use
|
||||
int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
|
||||
bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target
|
||||
};
|
||||
|
||||
//
|
||||
// The behaviors from the GLSL "#extension extension_name : behavior"
|
||||
//
|
||||
typedef enum {
|
||||
EBhMissing = 0,
|
||||
EBhRequire,
|
||||
EBhEnable,
|
||||
EBhWarn,
|
||||
EBhDisable,
|
||||
EBhDisablePartial // use as initial state of an extension that is only partially implemented
|
||||
} TExtensionBehavior;
|
||||
|
||||
//
|
||||
// Symbolic names for extensions. Strings may be directly used when calling the
|
||||
// functions, but better to have the compiler do spelling checks.
|
||||
//
|
||||
const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D";
|
||||
const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives";
|
||||
const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth";
|
||||
const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
|
||||
const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3";
|
||||
const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target";
|
||||
const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod";
|
||||
const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers";
|
||||
|
||||
const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle";
|
||||
const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects";
|
||||
const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack";
|
||||
const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather";
|
||||
const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5";
|
||||
const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects";
|
||||
const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader";
|
||||
const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader";
|
||||
const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts";
|
||||
const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array";
|
||||
const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample";
|
||||
const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod";
|
||||
const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location";
|
||||
const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location";
|
||||
const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store";
|
||||
const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters";
|
||||
const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters";
|
||||
const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote";
|
||||
const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control";
|
||||
const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples";
|
||||
const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array";
|
||||
const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64";
|
||||
const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64";
|
||||
const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot";
|
||||
const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2";
|
||||
const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp";
|
||||
const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export";
|
||||
// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members
|
||||
const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage";
|
||||
const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array";
|
||||
const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock";
|
||||
const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock";
|
||||
const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object";
|
||||
const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading";
|
||||
const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding";
|
||||
const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size";
|
||||
const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object";
|
||||
const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing";
|
||||
const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod";
|
||||
const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit";
|
||||
|
||||
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
|
||||
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
|
||||
const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic";
|
||||
const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot";
|
||||
const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle";
|
||||
const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
|
||||
const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered";
|
||||
const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad";
|
||||
const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics";
|
||||
|
||||
const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64";
|
||||
|
||||
const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
|
||||
const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
|
||||
|
||||
const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage";
|
||||
const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage";
|
||||
|
||||
|
||||
// EXT extensions
|
||||
const char* const E_GL_EXT_device_group = "GL_EXT_device_group";
|
||||
const char* const E_GL_EXT_multiview = "GL_EXT_multiview";
|
||||
const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage";
|
||||
const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes";
|
||||
const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier";
|
||||
const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions";
|
||||
const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout";
|
||||
const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density";
|
||||
const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference";
|
||||
const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2";
|
||||
const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2";
|
||||
const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation";
|
||||
const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock";
|
||||
const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf";
|
||||
const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing";
|
||||
const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query";
|
||||
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
|
||||
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
|
||||
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
|
||||
const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate";
|
||||
const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64";
|
||||
const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer";
|
||||
const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block";
|
||||
|
||||
// Arrays of extensions for the above viewportEXTs duplications
|
||||
|
||||
const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage };
|
||||
const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]);
|
||||
|
||||
// OVR extensions
|
||||
const char* const E_GL_OVR_multiview = "GL_OVR_multiview";
|
||||
const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2";
|
||||
|
||||
const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 };
|
||||
const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]);
|
||||
|
||||
// #line and #include
|
||||
const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
|
||||
const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive";
|
||||
|
||||
const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot";
|
||||
const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax";
|
||||
const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter";
|
||||
const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader";
|
||||
const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float";
|
||||
const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod";
|
||||
const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16";
|
||||
const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod";
|
||||
const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask";
|
||||
const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch";
|
||||
|
||||
const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2";
|
||||
|
||||
const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage";
|
||||
const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough";
|
||||
const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2";
|
||||
const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering";
|
||||
const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes";
|
||||
const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64";
|
||||
const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation";
|
||||
const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation";
|
||||
const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned";
|
||||
const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image";
|
||||
const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing";
|
||||
const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric";
|
||||
const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives";
|
||||
const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint";
|
||||
const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader";
|
||||
|
||||
// Arrays of extensions for the above viewportEXTs duplications
|
||||
|
||||
const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 };
|
||||
const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]);
|
||||
|
||||
const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix";
|
||||
const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins";
|
||||
const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix";
|
||||
|
||||
// AEP
|
||||
const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a";
|
||||
const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced";
|
||||
const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables";
|
||||
const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic";
|
||||
const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation";
|
||||
const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array";
|
||||
const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader";
|
||||
const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size";
|
||||
const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5";
|
||||
const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box";
|
||||
const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks";
|
||||
const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader";
|
||||
const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size";
|
||||
const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
|
||||
const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
|
||||
const char* const E_GL_EXT_shader_integer_mix = "GL_EXT_shader_integer_mix";
|
||||
|
||||
// OES matching AEP
|
||||
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
|
||||
const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size";
|
||||
const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5";
|
||||
const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box";
|
||||
const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks";
|
||||
const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader";
|
||||
const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size";
|
||||
const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer";
|
||||
const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array";
|
||||
|
||||
// EXT
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32";
|
||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64";
|
||||
|
||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8";
|
||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
|
||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
|
||||
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
|
||||
const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation";
|
||||
|
||||
const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
|
||||
|
||||
// Arrays of extensions for the above AEP duplications
|
||||
|
||||
const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };
|
||||
const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]);
|
||||
|
||||
const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size };
|
||||
const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]);
|
||||
|
||||
const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 };
|
||||
const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]);
|
||||
|
||||
const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box };
|
||||
const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]);
|
||||
|
||||
const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks };
|
||||
const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]);
|
||||
|
||||
const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader };
|
||||
const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]);
|
||||
|
||||
const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size };
|
||||
const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]);
|
||||
|
||||
const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer };
|
||||
const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]);
|
||||
|
||||
const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array };
|
||||
const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]);
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _VERSIONS_INCLUDED_
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
//
|
||||
// Copyright (C) 2017 LunarG, Inc.
|
||||
// Copyright (C) 2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _ATTRIBUTE_INCLUDED_
|
||||
#define _ATTRIBUTE_INCLUDED_
|
||||
|
||||
#include "../Include/Common.h"
|
||||
#include "../Include/ConstantUnion.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
enum TAttributeType {
|
||||
EatNone,
|
||||
EatAllow_uav_condition,
|
||||
EatBranch,
|
||||
EatCall,
|
||||
EatDomain,
|
||||
EatEarlyDepthStencil,
|
||||
EatFastOpt,
|
||||
EatFlatten,
|
||||
EatForceCase,
|
||||
EatInstance,
|
||||
EatMaxTessFactor,
|
||||
EatNumThreads,
|
||||
EatMaxVertexCount,
|
||||
EatOutputControlPoints,
|
||||
EatOutputTopology,
|
||||
EatPartitioning,
|
||||
EatPatchConstantFunc,
|
||||
EatPatchSize,
|
||||
EatUnroll,
|
||||
EatLoop,
|
||||
EatBinding,
|
||||
EatGlobalBinding,
|
||||
EatLocation,
|
||||
EatInputAttachment,
|
||||
EatBuiltIn,
|
||||
EatPushConstant,
|
||||
EatConstantId,
|
||||
EatDependencyInfinite,
|
||||
EatDependencyLength,
|
||||
EatMinIterations,
|
||||
EatMaxIterations,
|
||||
EatIterationMultiple,
|
||||
EatPeelCount,
|
||||
EatPartialCount,
|
||||
EatFormatRgba32f,
|
||||
EatFormatRgba16f,
|
||||
EatFormatR32f,
|
||||
EatFormatRgba8,
|
||||
EatFormatRgba8Snorm,
|
||||
EatFormatRg32f,
|
||||
EatFormatRg16f,
|
||||
EatFormatR11fG11fB10f,
|
||||
EatFormatR16f,
|
||||
EatFormatRgba16,
|
||||
EatFormatRgb10A2,
|
||||
EatFormatRg16,
|
||||
EatFormatRg8,
|
||||
EatFormatR16,
|
||||
EatFormatR8,
|
||||
EatFormatRgba16Snorm,
|
||||
EatFormatRg16Snorm,
|
||||
EatFormatRg8Snorm,
|
||||
EatFormatR16Snorm,
|
||||
EatFormatR8Snorm,
|
||||
EatFormatRgba32i,
|
||||
EatFormatRgba16i,
|
||||
EatFormatRgba8i,
|
||||
EatFormatR32i,
|
||||
EatFormatRg32i,
|
||||
EatFormatRg16i,
|
||||
EatFormatRg8i,
|
||||
EatFormatR16i,
|
||||
EatFormatR8i,
|
||||
EatFormatRgba32ui,
|
||||
EatFormatRgba16ui,
|
||||
EatFormatRgba8ui,
|
||||
EatFormatR32ui,
|
||||
EatFormatRgb10a2ui,
|
||||
EatFormatRg32ui,
|
||||
EatFormatRg16ui,
|
||||
EatFormatRg8ui,
|
||||
EatFormatR16ui,
|
||||
EatFormatR8ui,
|
||||
EatFormatUnknown,
|
||||
EatNonWritable,
|
||||
EatNonReadable
|
||||
};
|
||||
|
||||
class TIntermAggregate;
|
||||
|
||||
struct TAttributeArgs {
|
||||
TAttributeType name;
|
||||
const TIntermAggregate* args;
|
||||
|
||||
// Obtain attribute as integer
|
||||
// Return false if it cannot be obtained
|
||||
bool getInt(int& value, int argNum = 0) const;
|
||||
|
||||
// Obtain attribute as string, with optional to-lower transform
|
||||
// Return false if it cannot be obtained
|
||||
bool getString(TString& value, int argNum = 0, bool convertToLower = true) const;
|
||||
|
||||
// How many arguments were provided to the attribute?
|
||||
int size() const;
|
||||
|
||||
protected:
|
||||
const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const;
|
||||
};
|
||||
|
||||
typedef TList<TAttributeArgs> TAttributes;
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _ATTRIBUTE_INCLUDED_
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
** Copyright (c) 2013 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FLOAT_VEC2 0x8B50
|
||||
#define GL_FLOAT_VEC3 0x8B51
|
||||
#define GL_FLOAT_VEC4 0x8B52
|
||||
|
||||
#define GL_DOUBLE 0x140A
|
||||
#define GL_DOUBLE_VEC2 0x8FFC
|
||||
#define GL_DOUBLE_VEC3 0x8FFD
|
||||
#define GL_DOUBLE_VEC4 0x8FFE
|
||||
|
||||
#define GL_INT 0x1404
|
||||
#define GL_INT_VEC2 0x8B53
|
||||
#define GL_INT_VEC3 0x8B54
|
||||
#define GL_INT_VEC4 0x8B55
|
||||
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_UNSIGNED_INT_VEC2 0x8DC6
|
||||
#define GL_UNSIGNED_INT_VEC3 0x8DC7
|
||||
#define GL_UNSIGNED_INT_VEC4 0x8DC8
|
||||
|
||||
#define GL_INT64_ARB 0x140E
|
||||
#define GL_INT64_VEC2_ARB 0x8FE9
|
||||
#define GL_INT64_VEC3_ARB 0x8FEA
|
||||
#define GL_INT64_VEC4_ARB 0x8FEB
|
||||
|
||||
#define GL_UNSIGNED_INT64_ARB 0x140F
|
||||
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
|
||||
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
|
||||
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
|
||||
#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
|
||||
#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
|
||||
#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
|
||||
|
||||
#define GL_INT16_NV 0x8FE4
|
||||
#define GL_INT16_VEC2_NV 0x8FE5
|
||||
#define GL_INT16_VEC3_NV 0x8FE6
|
||||
#define GL_INT16_VEC4_NV 0x8FE7
|
||||
|
||||
#define GL_BOOL 0x8B56
|
||||
#define GL_BOOL_VEC2 0x8B57
|
||||
#define GL_BOOL_VEC3 0x8B58
|
||||
#define GL_BOOL_VEC4 0x8B59
|
||||
|
||||
#define GL_FLOAT_MAT2 0x8B5A
|
||||
#define GL_FLOAT_MAT3 0x8B5B
|
||||
#define GL_FLOAT_MAT4 0x8B5C
|
||||
#define GL_FLOAT_MAT2x3 0x8B65
|
||||
#define GL_FLOAT_MAT2x4 0x8B66
|
||||
#define GL_FLOAT_MAT3x2 0x8B67
|
||||
#define GL_FLOAT_MAT3x4 0x8B68
|
||||
#define GL_FLOAT_MAT4x2 0x8B69
|
||||
#define GL_FLOAT_MAT4x3 0x8B6A
|
||||
|
||||
#define GL_DOUBLE_MAT2 0x8F46
|
||||
#define GL_DOUBLE_MAT3 0x8F47
|
||||
#define GL_DOUBLE_MAT4 0x8F48
|
||||
#define GL_DOUBLE_MAT2x3 0x8F49
|
||||
#define GL_DOUBLE_MAT2x4 0x8F4A
|
||||
#define GL_DOUBLE_MAT3x2 0x8F4B
|
||||
#define GL_DOUBLE_MAT3x4 0x8F4C
|
||||
#define GL_DOUBLE_MAT4x2 0x8F4D
|
||||
#define GL_DOUBLE_MAT4x3 0x8F4E
|
||||
|
||||
// Those constants are borrowed from extension NV_gpu_shader5
|
||||
#define GL_FLOAT16_NV 0x8FF8
|
||||
#define GL_FLOAT16_VEC2_NV 0x8FF9
|
||||
#define GL_FLOAT16_VEC3_NV 0x8FFA
|
||||
#define GL_FLOAT16_VEC4_NV 0x8FFB
|
||||
|
||||
#define GL_FLOAT16_MAT2_AMD 0x91C5
|
||||
#define GL_FLOAT16_MAT3_AMD 0x91C6
|
||||
#define GL_FLOAT16_MAT4_AMD 0x91C7
|
||||
#define GL_FLOAT16_MAT2x3_AMD 0x91C8
|
||||
#define GL_FLOAT16_MAT2x4_AMD 0x91C9
|
||||
#define GL_FLOAT16_MAT3x2_AMD 0x91CA
|
||||
#define GL_FLOAT16_MAT3x4_AMD 0x91CB
|
||||
#define GL_FLOAT16_MAT4x2_AMD 0x91CC
|
||||
#define GL_FLOAT16_MAT4x3_AMD 0x91CD
|
||||
|
||||
#define GL_SAMPLER_1D 0x8B5D
|
||||
#define GL_SAMPLER_2D 0x8B5E
|
||||
#define GL_SAMPLER_3D 0x8B5F
|
||||
#define GL_SAMPLER_CUBE 0x8B60
|
||||
#define GL_SAMPLER_BUFFER 0x8DC2
|
||||
#define GL_SAMPLER_1D_ARRAY 0x8DC0
|
||||
#define GL_SAMPLER_2D_ARRAY 0x8DC1
|
||||
#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
|
||||
#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
|
||||
#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
|
||||
#define GL_SAMPLER_1D_SHADOW 0x8B61
|
||||
#define GL_SAMPLER_2D_SHADOW 0x8B62
|
||||
#define GL_SAMPLER_2D_RECT 0x8B63
|
||||
#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
|
||||
#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
|
||||
#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
|
||||
#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
|
||||
#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
|
||||
#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
|
||||
#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
|
||||
|
||||
#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE
|
||||
#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF
|
||||
#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0
|
||||
#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1
|
||||
#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2
|
||||
#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3
|
||||
#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4
|
||||
#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5
|
||||
#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6
|
||||
#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7
|
||||
#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8
|
||||
|
||||
#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9
|
||||
#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA
|
||||
#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB
|
||||
#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC
|
||||
#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD
|
||||
#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE
|
||||
#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF
|
||||
|
||||
#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0
|
||||
#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1
|
||||
#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2
|
||||
#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3
|
||||
#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4
|
||||
#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5
|
||||
#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6
|
||||
#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7
|
||||
#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8
|
||||
#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9
|
||||
#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA
|
||||
|
||||
#define GL_INT_SAMPLER_1D 0x8DC9
|
||||
#define GL_INT_SAMPLER_2D 0x8DCA
|
||||
#define GL_INT_SAMPLER_3D 0x8DCB
|
||||
#define GL_INT_SAMPLER_CUBE 0x8DCC
|
||||
#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
|
||||
#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
|
||||
#define GL_INT_SAMPLER_2D_RECT 0x8DCD
|
||||
#define GL_INT_SAMPLER_BUFFER 0x8DD0
|
||||
#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
|
||||
#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
|
||||
#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
|
||||
#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
|
||||
|
||||
#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
|
||||
#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
|
||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
|
||||
#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
|
||||
#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
|
||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
|
||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
|
||||
|
||||
#define GL_IMAGE_1D 0x904C
|
||||
#define GL_IMAGE_2D 0x904D
|
||||
#define GL_IMAGE_3D 0x904E
|
||||
#define GL_IMAGE_2D_RECT 0x904F
|
||||
#define GL_IMAGE_CUBE 0x9050
|
||||
#define GL_IMAGE_BUFFER 0x9051
|
||||
#define GL_IMAGE_1D_ARRAY 0x9052
|
||||
#define GL_IMAGE_2D_ARRAY 0x9053
|
||||
#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
|
||||
#define GL_IMAGE_2D_MULTISAMPLE 0x9055
|
||||
#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
|
||||
#define GL_INT_IMAGE_1D 0x9057
|
||||
#define GL_INT_IMAGE_2D 0x9058
|
||||
#define GL_INT_IMAGE_3D 0x9059
|
||||
#define GL_INT_IMAGE_2D_RECT 0x905A
|
||||
#define GL_INT_IMAGE_CUBE 0x905B
|
||||
#define GL_INT_IMAGE_BUFFER 0x905C
|
||||
#define GL_INT_IMAGE_1D_ARRAY 0x905D
|
||||
#define GL_INT_IMAGE_2D_ARRAY 0x905E
|
||||
#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
|
||||
#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
|
||||
#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
|
||||
#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
|
||||
#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
|
||||
#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
|
||||
#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
|
||||
#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
|
||||
#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
|
||||
#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
|
||||
#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
|
||||
#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
|
||||
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
|
||||
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
|
||||
|
||||
#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
|
||||
|
|
@ -0,0 +1,555 @@
|
|||
/* A Bison parser, made by GNU Bison 3.7.4. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* 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_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
||||
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 1
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
/* Token kinds. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
enum yytokentype
|
||||
{
|
||||
YYEMPTY = -2,
|
||||
YYEOF = 0, /* "end of file" */
|
||||
YYerror = 256, /* error */
|
||||
YYUNDEF = 257, /* "invalid token" */
|
||||
CONST = 258, /* CONST */
|
||||
BOOL = 259, /* BOOL */
|
||||
INT = 260, /* INT */
|
||||
UINT = 261, /* UINT */
|
||||
FLOAT = 262, /* FLOAT */
|
||||
BVEC2 = 263, /* BVEC2 */
|
||||
BVEC3 = 264, /* BVEC3 */
|
||||
BVEC4 = 265, /* BVEC4 */
|
||||
IVEC2 = 266, /* IVEC2 */
|
||||
IVEC3 = 267, /* IVEC3 */
|
||||
IVEC4 = 268, /* IVEC4 */
|
||||
UVEC2 = 269, /* UVEC2 */
|
||||
UVEC3 = 270, /* UVEC3 */
|
||||
UVEC4 = 271, /* UVEC4 */
|
||||
VEC2 = 272, /* VEC2 */
|
||||
VEC3 = 273, /* VEC3 */
|
||||
VEC4 = 274, /* VEC4 */
|
||||
MAT2 = 275, /* MAT2 */
|
||||
MAT3 = 276, /* MAT3 */
|
||||
MAT4 = 277, /* MAT4 */
|
||||
MAT2X2 = 278, /* MAT2X2 */
|
||||
MAT2X3 = 279, /* MAT2X3 */
|
||||
MAT2X4 = 280, /* MAT2X4 */
|
||||
MAT3X2 = 281, /* MAT3X2 */
|
||||
MAT3X3 = 282, /* MAT3X3 */
|
||||
MAT3X4 = 283, /* MAT3X4 */
|
||||
MAT4X2 = 284, /* MAT4X2 */
|
||||
MAT4X3 = 285, /* MAT4X3 */
|
||||
MAT4X4 = 286, /* MAT4X4 */
|
||||
SAMPLER2D = 287, /* SAMPLER2D */
|
||||
SAMPLER3D = 288, /* SAMPLER3D */
|
||||
SAMPLERCUBE = 289, /* SAMPLERCUBE */
|
||||
SAMPLER2DSHADOW = 290, /* SAMPLER2DSHADOW */
|
||||
SAMPLERCUBESHADOW = 291, /* SAMPLERCUBESHADOW */
|
||||
SAMPLER2DARRAY = 292, /* SAMPLER2DARRAY */
|
||||
SAMPLER2DARRAYSHADOW = 293, /* SAMPLER2DARRAYSHADOW */
|
||||
ISAMPLER2D = 294, /* ISAMPLER2D */
|
||||
ISAMPLER3D = 295, /* ISAMPLER3D */
|
||||
ISAMPLERCUBE = 296, /* ISAMPLERCUBE */
|
||||
ISAMPLER2DARRAY = 297, /* ISAMPLER2DARRAY */
|
||||
USAMPLER2D = 298, /* USAMPLER2D */
|
||||
USAMPLER3D = 299, /* USAMPLER3D */
|
||||
USAMPLERCUBE = 300, /* USAMPLERCUBE */
|
||||
USAMPLER2DARRAY = 301, /* USAMPLER2DARRAY */
|
||||
SAMPLER = 302, /* SAMPLER */
|
||||
SAMPLERSHADOW = 303, /* SAMPLERSHADOW */
|
||||
TEXTURE2D = 304, /* TEXTURE2D */
|
||||
TEXTURE3D = 305, /* TEXTURE3D */
|
||||
TEXTURECUBE = 306, /* TEXTURECUBE */
|
||||
TEXTURE2DARRAY = 307, /* TEXTURE2DARRAY */
|
||||
ITEXTURE2D = 308, /* ITEXTURE2D */
|
||||
ITEXTURE3D = 309, /* ITEXTURE3D */
|
||||
ITEXTURECUBE = 310, /* ITEXTURECUBE */
|
||||
ITEXTURE2DARRAY = 311, /* ITEXTURE2DARRAY */
|
||||
UTEXTURE2D = 312, /* UTEXTURE2D */
|
||||
UTEXTURE3D = 313, /* UTEXTURE3D */
|
||||
UTEXTURECUBE = 314, /* UTEXTURECUBE */
|
||||
UTEXTURE2DARRAY = 315, /* UTEXTURE2DARRAY */
|
||||
ATTRIBUTE = 316, /* ATTRIBUTE */
|
||||
VARYING = 317, /* VARYING */
|
||||
FLOAT16_T = 318, /* FLOAT16_T */
|
||||
FLOAT32_T = 319, /* FLOAT32_T */
|
||||
DOUBLE = 320, /* DOUBLE */
|
||||
FLOAT64_T = 321, /* FLOAT64_T */
|
||||
INT64_T = 322, /* INT64_T */
|
||||
UINT64_T = 323, /* UINT64_T */
|
||||
INT32_T = 324, /* INT32_T */
|
||||
UINT32_T = 325, /* UINT32_T */
|
||||
INT16_T = 326, /* INT16_T */
|
||||
UINT16_T = 327, /* UINT16_T */
|
||||
INT8_T = 328, /* INT8_T */
|
||||
UINT8_T = 329, /* UINT8_T */
|
||||
I64VEC2 = 330, /* I64VEC2 */
|
||||
I64VEC3 = 331, /* I64VEC3 */
|
||||
I64VEC4 = 332, /* I64VEC4 */
|
||||
U64VEC2 = 333, /* U64VEC2 */
|
||||
U64VEC3 = 334, /* U64VEC3 */
|
||||
U64VEC4 = 335, /* U64VEC4 */
|
||||
I32VEC2 = 336, /* I32VEC2 */
|
||||
I32VEC3 = 337, /* I32VEC3 */
|
||||
I32VEC4 = 338, /* I32VEC4 */
|
||||
U32VEC2 = 339, /* U32VEC2 */
|
||||
U32VEC3 = 340, /* U32VEC3 */
|
||||
U32VEC4 = 341, /* U32VEC4 */
|
||||
I16VEC2 = 342, /* I16VEC2 */
|
||||
I16VEC3 = 343, /* I16VEC3 */
|
||||
I16VEC4 = 344, /* I16VEC4 */
|
||||
U16VEC2 = 345, /* U16VEC2 */
|
||||
U16VEC3 = 346, /* U16VEC3 */
|
||||
U16VEC4 = 347, /* U16VEC4 */
|
||||
I8VEC2 = 348, /* I8VEC2 */
|
||||
I8VEC3 = 349, /* I8VEC3 */
|
||||
I8VEC4 = 350, /* I8VEC4 */
|
||||
U8VEC2 = 351, /* U8VEC2 */
|
||||
U8VEC3 = 352, /* U8VEC3 */
|
||||
U8VEC4 = 353, /* U8VEC4 */
|
||||
DVEC2 = 354, /* DVEC2 */
|
||||
DVEC3 = 355, /* DVEC3 */
|
||||
DVEC4 = 356, /* DVEC4 */
|
||||
DMAT2 = 357, /* DMAT2 */
|
||||
DMAT3 = 358, /* DMAT3 */
|
||||
DMAT4 = 359, /* DMAT4 */
|
||||
F16VEC2 = 360, /* F16VEC2 */
|
||||
F16VEC3 = 361, /* F16VEC3 */
|
||||
F16VEC4 = 362, /* F16VEC4 */
|
||||
F16MAT2 = 363, /* F16MAT2 */
|
||||
F16MAT3 = 364, /* F16MAT3 */
|
||||
F16MAT4 = 365, /* F16MAT4 */
|
||||
F32VEC2 = 366, /* F32VEC2 */
|
||||
F32VEC3 = 367, /* F32VEC3 */
|
||||
F32VEC4 = 368, /* F32VEC4 */
|
||||
F32MAT2 = 369, /* F32MAT2 */
|
||||
F32MAT3 = 370, /* F32MAT3 */
|
||||
F32MAT4 = 371, /* F32MAT4 */
|
||||
F64VEC2 = 372, /* F64VEC2 */
|
||||
F64VEC3 = 373, /* F64VEC3 */
|
||||
F64VEC4 = 374, /* F64VEC4 */
|
||||
F64MAT2 = 375, /* F64MAT2 */
|
||||
F64MAT3 = 376, /* F64MAT3 */
|
||||
F64MAT4 = 377, /* F64MAT4 */
|
||||
DMAT2X2 = 378, /* DMAT2X2 */
|
||||
DMAT2X3 = 379, /* DMAT2X3 */
|
||||
DMAT2X4 = 380, /* DMAT2X4 */
|
||||
DMAT3X2 = 381, /* DMAT3X2 */
|
||||
DMAT3X3 = 382, /* DMAT3X3 */
|
||||
DMAT3X4 = 383, /* DMAT3X4 */
|
||||
DMAT4X2 = 384, /* DMAT4X2 */
|
||||
DMAT4X3 = 385, /* DMAT4X3 */
|
||||
DMAT4X4 = 386, /* DMAT4X4 */
|
||||
F16MAT2X2 = 387, /* F16MAT2X2 */
|
||||
F16MAT2X3 = 388, /* F16MAT2X3 */
|
||||
F16MAT2X4 = 389, /* F16MAT2X4 */
|
||||
F16MAT3X2 = 390, /* F16MAT3X2 */
|
||||
F16MAT3X3 = 391, /* F16MAT3X3 */
|
||||
F16MAT3X4 = 392, /* F16MAT3X4 */
|
||||
F16MAT4X2 = 393, /* F16MAT4X2 */
|
||||
F16MAT4X3 = 394, /* F16MAT4X3 */
|
||||
F16MAT4X4 = 395, /* F16MAT4X4 */
|
||||
F32MAT2X2 = 396, /* F32MAT2X2 */
|
||||
F32MAT2X3 = 397, /* F32MAT2X3 */
|
||||
F32MAT2X4 = 398, /* F32MAT2X4 */
|
||||
F32MAT3X2 = 399, /* F32MAT3X2 */
|
||||
F32MAT3X3 = 400, /* F32MAT3X3 */
|
||||
F32MAT3X4 = 401, /* F32MAT3X4 */
|
||||
F32MAT4X2 = 402, /* F32MAT4X2 */
|
||||
F32MAT4X3 = 403, /* F32MAT4X3 */
|
||||
F32MAT4X4 = 404, /* F32MAT4X4 */
|
||||
F64MAT2X2 = 405, /* F64MAT2X2 */
|
||||
F64MAT2X3 = 406, /* F64MAT2X3 */
|
||||
F64MAT2X4 = 407, /* F64MAT2X4 */
|
||||
F64MAT3X2 = 408, /* F64MAT3X2 */
|
||||
F64MAT3X3 = 409, /* F64MAT3X3 */
|
||||
F64MAT3X4 = 410, /* F64MAT3X4 */
|
||||
F64MAT4X2 = 411, /* F64MAT4X2 */
|
||||
F64MAT4X3 = 412, /* F64MAT4X3 */
|
||||
F64MAT4X4 = 413, /* F64MAT4X4 */
|
||||
ATOMIC_UINT = 414, /* ATOMIC_UINT */
|
||||
ACCSTRUCTNV = 415, /* ACCSTRUCTNV */
|
||||
ACCSTRUCTEXT = 416, /* ACCSTRUCTEXT */
|
||||
RAYQUERYEXT = 417, /* RAYQUERYEXT */
|
||||
FCOOPMATNV = 418, /* FCOOPMATNV */
|
||||
ICOOPMATNV = 419, /* ICOOPMATNV */
|
||||
UCOOPMATNV = 420, /* UCOOPMATNV */
|
||||
SAMPLERCUBEARRAY = 421, /* SAMPLERCUBEARRAY */
|
||||
SAMPLERCUBEARRAYSHADOW = 422, /* SAMPLERCUBEARRAYSHADOW */
|
||||
ISAMPLERCUBEARRAY = 423, /* ISAMPLERCUBEARRAY */
|
||||
USAMPLERCUBEARRAY = 424, /* USAMPLERCUBEARRAY */
|
||||
SAMPLER1D = 425, /* SAMPLER1D */
|
||||
SAMPLER1DARRAY = 426, /* SAMPLER1DARRAY */
|
||||
SAMPLER1DARRAYSHADOW = 427, /* SAMPLER1DARRAYSHADOW */
|
||||
ISAMPLER1D = 428, /* ISAMPLER1D */
|
||||
SAMPLER1DSHADOW = 429, /* SAMPLER1DSHADOW */
|
||||
SAMPLER2DRECT = 430, /* SAMPLER2DRECT */
|
||||
SAMPLER2DRECTSHADOW = 431, /* SAMPLER2DRECTSHADOW */
|
||||
ISAMPLER2DRECT = 432, /* ISAMPLER2DRECT */
|
||||
USAMPLER2DRECT = 433, /* USAMPLER2DRECT */
|
||||
SAMPLERBUFFER = 434, /* SAMPLERBUFFER */
|
||||
ISAMPLERBUFFER = 435, /* ISAMPLERBUFFER */
|
||||
USAMPLERBUFFER = 436, /* USAMPLERBUFFER */
|
||||
SAMPLER2DMS = 437, /* SAMPLER2DMS */
|
||||
ISAMPLER2DMS = 438, /* ISAMPLER2DMS */
|
||||
USAMPLER2DMS = 439, /* USAMPLER2DMS */
|
||||
SAMPLER2DMSARRAY = 440, /* SAMPLER2DMSARRAY */
|
||||
ISAMPLER2DMSARRAY = 441, /* ISAMPLER2DMSARRAY */
|
||||
USAMPLER2DMSARRAY = 442, /* USAMPLER2DMSARRAY */
|
||||
SAMPLEREXTERNALOES = 443, /* SAMPLEREXTERNALOES */
|
||||
SAMPLEREXTERNAL2DY2YEXT = 444, /* SAMPLEREXTERNAL2DY2YEXT */
|
||||
ISAMPLER1DARRAY = 445, /* ISAMPLER1DARRAY */
|
||||
USAMPLER1D = 446, /* USAMPLER1D */
|
||||
USAMPLER1DARRAY = 447, /* USAMPLER1DARRAY */
|
||||
F16SAMPLER1D = 448, /* F16SAMPLER1D */
|
||||
F16SAMPLER2D = 449, /* F16SAMPLER2D */
|
||||
F16SAMPLER3D = 450, /* F16SAMPLER3D */
|
||||
F16SAMPLER2DRECT = 451, /* F16SAMPLER2DRECT */
|
||||
F16SAMPLERCUBE = 452, /* F16SAMPLERCUBE */
|
||||
F16SAMPLER1DARRAY = 453, /* F16SAMPLER1DARRAY */
|
||||
F16SAMPLER2DARRAY = 454, /* F16SAMPLER2DARRAY */
|
||||
F16SAMPLERCUBEARRAY = 455, /* F16SAMPLERCUBEARRAY */
|
||||
F16SAMPLERBUFFER = 456, /* F16SAMPLERBUFFER */
|
||||
F16SAMPLER2DMS = 457, /* F16SAMPLER2DMS */
|
||||
F16SAMPLER2DMSARRAY = 458, /* F16SAMPLER2DMSARRAY */
|
||||
F16SAMPLER1DSHADOW = 459, /* F16SAMPLER1DSHADOW */
|
||||
F16SAMPLER2DSHADOW = 460, /* F16SAMPLER2DSHADOW */
|
||||
F16SAMPLER1DARRAYSHADOW = 461, /* F16SAMPLER1DARRAYSHADOW */
|
||||
F16SAMPLER2DARRAYSHADOW = 462, /* F16SAMPLER2DARRAYSHADOW */
|
||||
F16SAMPLER2DRECTSHADOW = 463, /* F16SAMPLER2DRECTSHADOW */
|
||||
F16SAMPLERCUBESHADOW = 464, /* F16SAMPLERCUBESHADOW */
|
||||
F16SAMPLERCUBEARRAYSHADOW = 465, /* F16SAMPLERCUBEARRAYSHADOW */
|
||||
IMAGE1D = 466, /* IMAGE1D */
|
||||
IIMAGE1D = 467, /* IIMAGE1D */
|
||||
UIMAGE1D = 468, /* UIMAGE1D */
|
||||
IMAGE2D = 469, /* IMAGE2D */
|
||||
IIMAGE2D = 470, /* IIMAGE2D */
|
||||
UIMAGE2D = 471, /* UIMAGE2D */
|
||||
IMAGE3D = 472, /* IMAGE3D */
|
||||
IIMAGE3D = 473, /* IIMAGE3D */
|
||||
UIMAGE3D = 474, /* UIMAGE3D */
|
||||
IMAGE2DRECT = 475, /* IMAGE2DRECT */
|
||||
IIMAGE2DRECT = 476, /* IIMAGE2DRECT */
|
||||
UIMAGE2DRECT = 477, /* UIMAGE2DRECT */
|
||||
IMAGECUBE = 478, /* IMAGECUBE */
|
||||
IIMAGECUBE = 479, /* IIMAGECUBE */
|
||||
UIMAGECUBE = 480, /* UIMAGECUBE */
|
||||
IMAGEBUFFER = 481, /* IMAGEBUFFER */
|
||||
IIMAGEBUFFER = 482, /* IIMAGEBUFFER */
|
||||
UIMAGEBUFFER = 483, /* UIMAGEBUFFER */
|
||||
IMAGE1DARRAY = 484, /* IMAGE1DARRAY */
|
||||
IIMAGE1DARRAY = 485, /* IIMAGE1DARRAY */
|
||||
UIMAGE1DARRAY = 486, /* UIMAGE1DARRAY */
|
||||
IMAGE2DARRAY = 487, /* IMAGE2DARRAY */
|
||||
IIMAGE2DARRAY = 488, /* IIMAGE2DARRAY */
|
||||
UIMAGE2DARRAY = 489, /* UIMAGE2DARRAY */
|
||||
IMAGECUBEARRAY = 490, /* IMAGECUBEARRAY */
|
||||
IIMAGECUBEARRAY = 491, /* IIMAGECUBEARRAY */
|
||||
UIMAGECUBEARRAY = 492, /* UIMAGECUBEARRAY */
|
||||
IMAGE2DMS = 493, /* IMAGE2DMS */
|
||||
IIMAGE2DMS = 494, /* IIMAGE2DMS */
|
||||
UIMAGE2DMS = 495, /* UIMAGE2DMS */
|
||||
IMAGE2DMSARRAY = 496, /* IMAGE2DMSARRAY */
|
||||
IIMAGE2DMSARRAY = 497, /* IIMAGE2DMSARRAY */
|
||||
UIMAGE2DMSARRAY = 498, /* UIMAGE2DMSARRAY */
|
||||
F16IMAGE1D = 499, /* F16IMAGE1D */
|
||||
F16IMAGE2D = 500, /* F16IMAGE2D */
|
||||
F16IMAGE3D = 501, /* F16IMAGE3D */
|
||||
F16IMAGE2DRECT = 502, /* F16IMAGE2DRECT */
|
||||
F16IMAGECUBE = 503, /* F16IMAGECUBE */
|
||||
F16IMAGE1DARRAY = 504, /* F16IMAGE1DARRAY */
|
||||
F16IMAGE2DARRAY = 505, /* F16IMAGE2DARRAY */
|
||||
F16IMAGECUBEARRAY = 506, /* F16IMAGECUBEARRAY */
|
||||
F16IMAGEBUFFER = 507, /* F16IMAGEBUFFER */
|
||||
F16IMAGE2DMS = 508, /* F16IMAGE2DMS */
|
||||
F16IMAGE2DMSARRAY = 509, /* F16IMAGE2DMSARRAY */
|
||||
I64IMAGE1D = 510, /* I64IMAGE1D */
|
||||
U64IMAGE1D = 511, /* U64IMAGE1D */
|
||||
I64IMAGE2D = 512, /* I64IMAGE2D */
|
||||
U64IMAGE2D = 513, /* U64IMAGE2D */
|
||||
I64IMAGE3D = 514, /* I64IMAGE3D */
|
||||
U64IMAGE3D = 515, /* U64IMAGE3D */
|
||||
I64IMAGE2DRECT = 516, /* I64IMAGE2DRECT */
|
||||
U64IMAGE2DRECT = 517, /* U64IMAGE2DRECT */
|
||||
I64IMAGECUBE = 518, /* I64IMAGECUBE */
|
||||
U64IMAGECUBE = 519, /* U64IMAGECUBE */
|
||||
I64IMAGEBUFFER = 520, /* I64IMAGEBUFFER */
|
||||
U64IMAGEBUFFER = 521, /* U64IMAGEBUFFER */
|
||||
I64IMAGE1DARRAY = 522, /* I64IMAGE1DARRAY */
|
||||
U64IMAGE1DARRAY = 523, /* U64IMAGE1DARRAY */
|
||||
I64IMAGE2DARRAY = 524, /* I64IMAGE2DARRAY */
|
||||
U64IMAGE2DARRAY = 525, /* U64IMAGE2DARRAY */
|
||||
I64IMAGECUBEARRAY = 526, /* I64IMAGECUBEARRAY */
|
||||
U64IMAGECUBEARRAY = 527, /* U64IMAGECUBEARRAY */
|
||||
I64IMAGE2DMS = 528, /* I64IMAGE2DMS */
|
||||
U64IMAGE2DMS = 529, /* U64IMAGE2DMS */
|
||||
I64IMAGE2DMSARRAY = 530, /* I64IMAGE2DMSARRAY */
|
||||
U64IMAGE2DMSARRAY = 531, /* U64IMAGE2DMSARRAY */
|
||||
TEXTURECUBEARRAY = 532, /* TEXTURECUBEARRAY */
|
||||
ITEXTURECUBEARRAY = 533, /* ITEXTURECUBEARRAY */
|
||||
UTEXTURECUBEARRAY = 534, /* UTEXTURECUBEARRAY */
|
||||
TEXTURE1D = 535, /* TEXTURE1D */
|
||||
ITEXTURE1D = 536, /* ITEXTURE1D */
|
||||
UTEXTURE1D = 537, /* UTEXTURE1D */
|
||||
TEXTURE1DARRAY = 538, /* TEXTURE1DARRAY */
|
||||
ITEXTURE1DARRAY = 539, /* ITEXTURE1DARRAY */
|
||||
UTEXTURE1DARRAY = 540, /* UTEXTURE1DARRAY */
|
||||
TEXTURE2DRECT = 541, /* TEXTURE2DRECT */
|
||||
ITEXTURE2DRECT = 542, /* ITEXTURE2DRECT */
|
||||
UTEXTURE2DRECT = 543, /* UTEXTURE2DRECT */
|
||||
TEXTUREBUFFER = 544, /* TEXTUREBUFFER */
|
||||
ITEXTUREBUFFER = 545, /* ITEXTUREBUFFER */
|
||||
UTEXTUREBUFFER = 546, /* UTEXTUREBUFFER */
|
||||
TEXTURE2DMS = 547, /* TEXTURE2DMS */
|
||||
ITEXTURE2DMS = 548, /* ITEXTURE2DMS */
|
||||
UTEXTURE2DMS = 549, /* UTEXTURE2DMS */
|
||||
TEXTURE2DMSARRAY = 550, /* TEXTURE2DMSARRAY */
|
||||
ITEXTURE2DMSARRAY = 551, /* ITEXTURE2DMSARRAY */
|
||||
UTEXTURE2DMSARRAY = 552, /* UTEXTURE2DMSARRAY */
|
||||
F16TEXTURE1D = 553, /* F16TEXTURE1D */
|
||||
F16TEXTURE2D = 554, /* F16TEXTURE2D */
|
||||
F16TEXTURE3D = 555, /* F16TEXTURE3D */
|
||||
F16TEXTURE2DRECT = 556, /* F16TEXTURE2DRECT */
|
||||
F16TEXTURECUBE = 557, /* F16TEXTURECUBE */
|
||||
F16TEXTURE1DARRAY = 558, /* F16TEXTURE1DARRAY */
|
||||
F16TEXTURE2DARRAY = 559, /* F16TEXTURE2DARRAY */
|
||||
F16TEXTURECUBEARRAY = 560, /* F16TEXTURECUBEARRAY */
|
||||
F16TEXTUREBUFFER = 561, /* F16TEXTUREBUFFER */
|
||||
F16TEXTURE2DMS = 562, /* F16TEXTURE2DMS */
|
||||
F16TEXTURE2DMSARRAY = 563, /* F16TEXTURE2DMSARRAY */
|
||||
SUBPASSINPUT = 564, /* SUBPASSINPUT */
|
||||
SUBPASSINPUTMS = 565, /* SUBPASSINPUTMS */
|
||||
ISUBPASSINPUT = 566, /* ISUBPASSINPUT */
|
||||
ISUBPASSINPUTMS = 567, /* ISUBPASSINPUTMS */
|
||||
USUBPASSINPUT = 568, /* USUBPASSINPUT */
|
||||
USUBPASSINPUTMS = 569, /* USUBPASSINPUTMS */
|
||||
F16SUBPASSINPUT = 570, /* F16SUBPASSINPUT */
|
||||
F16SUBPASSINPUTMS = 571, /* F16SUBPASSINPUTMS */
|
||||
LEFT_OP = 572, /* LEFT_OP */
|
||||
RIGHT_OP = 573, /* RIGHT_OP */
|
||||
INC_OP = 574, /* INC_OP */
|
||||
DEC_OP = 575, /* DEC_OP */
|
||||
LE_OP = 576, /* LE_OP */
|
||||
GE_OP = 577, /* GE_OP */
|
||||
EQ_OP = 578, /* EQ_OP */
|
||||
NE_OP = 579, /* NE_OP */
|
||||
AND_OP = 580, /* AND_OP */
|
||||
OR_OP = 581, /* OR_OP */
|
||||
XOR_OP = 582, /* XOR_OP */
|
||||
MUL_ASSIGN = 583, /* MUL_ASSIGN */
|
||||
DIV_ASSIGN = 584, /* DIV_ASSIGN */
|
||||
ADD_ASSIGN = 585, /* ADD_ASSIGN */
|
||||
MOD_ASSIGN = 586, /* MOD_ASSIGN */
|
||||
LEFT_ASSIGN = 587, /* LEFT_ASSIGN */
|
||||
RIGHT_ASSIGN = 588, /* RIGHT_ASSIGN */
|
||||
AND_ASSIGN = 589, /* AND_ASSIGN */
|
||||
XOR_ASSIGN = 590, /* XOR_ASSIGN */
|
||||
OR_ASSIGN = 591, /* OR_ASSIGN */
|
||||
SUB_ASSIGN = 592, /* SUB_ASSIGN */
|
||||
STRING_LITERAL = 593, /* STRING_LITERAL */
|
||||
LEFT_PAREN = 594, /* LEFT_PAREN */
|
||||
RIGHT_PAREN = 595, /* RIGHT_PAREN */
|
||||
LEFT_BRACKET = 596, /* LEFT_BRACKET */
|
||||
RIGHT_BRACKET = 597, /* RIGHT_BRACKET */
|
||||
LEFT_BRACE = 598, /* LEFT_BRACE */
|
||||
RIGHT_BRACE = 599, /* RIGHT_BRACE */
|
||||
DOT = 600, /* DOT */
|
||||
COMMA = 601, /* COMMA */
|
||||
COLON = 602, /* COLON */
|
||||
EQUAL = 603, /* EQUAL */
|
||||
SEMICOLON = 604, /* SEMICOLON */
|
||||
BANG = 605, /* BANG */
|
||||
DASH = 606, /* DASH */
|
||||
TILDE = 607, /* TILDE */
|
||||
PLUS = 608, /* PLUS */
|
||||
STAR = 609, /* STAR */
|
||||
SLASH = 610, /* SLASH */
|
||||
PERCENT = 611, /* PERCENT */
|
||||
LEFT_ANGLE = 612, /* LEFT_ANGLE */
|
||||
RIGHT_ANGLE = 613, /* RIGHT_ANGLE */
|
||||
VERTICAL_BAR = 614, /* VERTICAL_BAR */
|
||||
CARET = 615, /* CARET */
|
||||
AMPERSAND = 616, /* AMPERSAND */
|
||||
QUESTION = 617, /* QUESTION */
|
||||
INVARIANT = 618, /* INVARIANT */
|
||||
HIGH_PRECISION = 619, /* HIGH_PRECISION */
|
||||
MEDIUM_PRECISION = 620, /* MEDIUM_PRECISION */
|
||||
LOW_PRECISION = 621, /* LOW_PRECISION */
|
||||
PRECISION = 622, /* PRECISION */
|
||||
PACKED = 623, /* PACKED */
|
||||
RESOURCE = 624, /* RESOURCE */
|
||||
SUPERP = 625, /* SUPERP */
|
||||
FLOATCONSTANT = 626, /* FLOATCONSTANT */
|
||||
INTCONSTANT = 627, /* INTCONSTANT */
|
||||
UINTCONSTANT = 628, /* UINTCONSTANT */
|
||||
BOOLCONSTANT = 629, /* BOOLCONSTANT */
|
||||
IDENTIFIER = 630, /* IDENTIFIER */
|
||||
TYPE_NAME = 631, /* TYPE_NAME */
|
||||
CENTROID = 632, /* CENTROID */
|
||||
IN = 633, /* IN */
|
||||
OUT = 634, /* OUT */
|
||||
INOUT = 635, /* INOUT */
|
||||
STRUCT = 636, /* STRUCT */
|
||||
VOID = 637, /* VOID */
|
||||
WHILE = 638, /* WHILE */
|
||||
BREAK = 639, /* BREAK */
|
||||
CONTINUE = 640, /* CONTINUE */
|
||||
DO = 641, /* DO */
|
||||
ELSE = 642, /* ELSE */
|
||||
FOR = 643, /* FOR */
|
||||
IF = 644, /* IF */
|
||||
DISCARD = 645, /* DISCARD */
|
||||
RETURN = 646, /* RETURN */
|
||||
SWITCH = 647, /* SWITCH */
|
||||
CASE = 648, /* CASE */
|
||||
DEFAULT = 649, /* DEFAULT */
|
||||
TERMINATE_INVOCATION = 650, /* TERMINATE_INVOCATION */
|
||||
TERMINATE_RAY = 651, /* TERMINATE_RAY */
|
||||
IGNORE_INTERSECTION = 652, /* IGNORE_INTERSECTION */
|
||||
UNIFORM = 653, /* UNIFORM */
|
||||
SHARED = 654, /* SHARED */
|
||||
BUFFER = 655, /* BUFFER */
|
||||
FLAT = 656, /* FLAT */
|
||||
SMOOTH = 657, /* SMOOTH */
|
||||
LAYOUT = 658, /* LAYOUT */
|
||||
DOUBLECONSTANT = 659, /* DOUBLECONSTANT */
|
||||
INT16CONSTANT = 660, /* INT16CONSTANT */
|
||||
UINT16CONSTANT = 661, /* UINT16CONSTANT */
|
||||
FLOAT16CONSTANT = 662, /* FLOAT16CONSTANT */
|
||||
INT32CONSTANT = 663, /* INT32CONSTANT */
|
||||
UINT32CONSTANT = 664, /* UINT32CONSTANT */
|
||||
INT64CONSTANT = 665, /* INT64CONSTANT */
|
||||
UINT64CONSTANT = 666, /* UINT64CONSTANT */
|
||||
SUBROUTINE = 667, /* SUBROUTINE */
|
||||
DEMOTE = 668, /* DEMOTE */
|
||||
PAYLOADNV = 669, /* PAYLOADNV */
|
||||
PAYLOADINNV = 670, /* PAYLOADINNV */
|
||||
HITATTRNV = 671, /* HITATTRNV */
|
||||
CALLDATANV = 672, /* CALLDATANV */
|
||||
CALLDATAINNV = 673, /* CALLDATAINNV */
|
||||
PAYLOADEXT = 674, /* PAYLOADEXT */
|
||||
PAYLOADINEXT = 675, /* PAYLOADINEXT */
|
||||
HITATTREXT = 676, /* HITATTREXT */
|
||||
CALLDATAEXT = 677, /* CALLDATAEXT */
|
||||
CALLDATAINEXT = 678, /* CALLDATAINEXT */
|
||||
PATCH = 679, /* PATCH */
|
||||
SAMPLE = 680, /* SAMPLE */
|
||||
NONUNIFORM = 681, /* NONUNIFORM */
|
||||
COHERENT = 682, /* COHERENT */
|
||||
VOLATILE = 683, /* VOLATILE */
|
||||
RESTRICT = 684, /* RESTRICT */
|
||||
READONLY = 685, /* READONLY */
|
||||
WRITEONLY = 686, /* WRITEONLY */
|
||||
DEVICECOHERENT = 687, /* DEVICECOHERENT */
|
||||
QUEUEFAMILYCOHERENT = 688, /* QUEUEFAMILYCOHERENT */
|
||||
WORKGROUPCOHERENT = 689, /* WORKGROUPCOHERENT */
|
||||
SUBGROUPCOHERENT = 690, /* SUBGROUPCOHERENT */
|
||||
NONPRIVATE = 691, /* NONPRIVATE */
|
||||
SHADERCALLCOHERENT = 692, /* SHADERCALLCOHERENT */
|
||||
NOPERSPECTIVE = 693, /* NOPERSPECTIVE */
|
||||
EXPLICITINTERPAMD = 694, /* EXPLICITINTERPAMD */
|
||||
PERVERTEXNV = 695, /* PERVERTEXNV */
|
||||
PERPRIMITIVENV = 696, /* PERPRIMITIVENV */
|
||||
PERVIEWNV = 697, /* PERVIEWNV */
|
||||
PERTASKNV = 698, /* PERTASKNV */
|
||||
PRECISE = 699 /* PRECISE */
|
||||
};
|
||||
typedef enum yytokentype yytoken_kind_t;
|
||||
#endif
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
union YYSTYPE
|
||||
{
|
||||
#line 97 "MachineIndependent/glslang.y"
|
||||
|
||||
struct {
|
||||
glslang::TSourceLoc loc;
|
||||
union {
|
||||
glslang::TString *string;
|
||||
int i;
|
||||
unsigned int u;
|
||||
long long i64;
|
||||
unsigned long long u64;
|
||||
bool b;
|
||||
double d;
|
||||
};
|
||||
glslang::TSymbol* symbol;
|
||||
} lex;
|
||||
struct {
|
||||
glslang::TSourceLoc loc;
|
||||
glslang::TOperator op;
|
||||
union {
|
||||
TIntermNode* intermNode;
|
||||
glslang::TIntermNodePair nodePair;
|
||||
glslang::TIntermTyped* intermTypedNode;
|
||||
glslang::TAttributes* attributes;
|
||||
};
|
||||
union {
|
||||
glslang::TPublicType type;
|
||||
glslang::TFunction* function;
|
||||
glslang::TParameter param;
|
||||
glslang::TTypeLoc typeLine;
|
||||
glslang::TTypeList* typeList;
|
||||
glslang::TArraySizes* arraySizes;
|
||||
glslang::TIdentifierList* identifierList;
|
||||
};
|
||||
glslang::TArraySizes* typeParameters;
|
||||
} interm;
|
||||
|
||||
#line 544 "MachineIndependent/glslang_tab.cpp.h"
|
||||
|
||||
};
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int yyparse (glslang::TParseContext* pParseContext);
|
||||
|
||||
#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */
|
||||
|
|
@ -0,0 +1,338 @@
|
|||
//
|
||||
// Copyright (C) 2016 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
|
||||
#ifndef _IOMAPPER_INCLUDED
|
||||
#define _IOMAPPER_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include "LiveTraverser.h"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
//
|
||||
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
|
||||
//
|
||||
|
||||
class TInfoSink;
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TIntermediate;
|
||||
struct TVarEntryInfo {
|
||||
long long id;
|
||||
TIntermSymbol* symbol;
|
||||
bool live;
|
||||
int newBinding;
|
||||
int newSet;
|
||||
int newLocation;
|
||||
int newComponent;
|
||||
int newIndex;
|
||||
EShLanguage stage;
|
||||
struct TOrderById {
|
||||
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
|
||||
};
|
||||
|
||||
struct TOrderByPriority {
|
||||
// ordering:
|
||||
// 1) has both binding and set
|
||||
// 2) has binding but no set
|
||||
// 3) has no binding but set
|
||||
// 4) has no binding and no set
|
||||
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
|
||||
const TQualifier& lq = l.symbol->getQualifier();
|
||||
const TQualifier& rq = r.symbol->getQualifier();
|
||||
|
||||
// simple rules:
|
||||
// has binding gives 2 points
|
||||
// has set gives 1 point
|
||||
// who has the most points is more important.
|
||||
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
|
||||
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
|
||||
|
||||
if (lPoints == rPoints)
|
||||
return l.id < r.id;
|
||||
return lPoints > rPoints;
|
||||
}
|
||||
};
|
||||
|
||||
struct TOrderByPriorityAndLive {
|
||||
// ordering:
|
||||
// 1) do live variables first
|
||||
// 2) has both binding and set
|
||||
// 3) has binding but no set
|
||||
// 4) has no binding but set
|
||||
// 5) has no binding and no set
|
||||
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
|
||||
|
||||
const TQualifier& lq = l.symbol->getQualifier();
|
||||
const TQualifier& rq = r.symbol->getQualifier();
|
||||
|
||||
// simple rules:
|
||||
// has binding gives 2 points
|
||||
// has set gives 1 point
|
||||
// who has the most points is more important.
|
||||
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
|
||||
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
|
||||
|
||||
if (l.live != r.live)
|
||||
return l.live > r.live;
|
||||
|
||||
if (lPoints != rPoints)
|
||||
return lPoints > rPoints;
|
||||
|
||||
return l.id < r.id;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Base class for shared TIoMapResolver services, used by several derivations.
|
||||
struct TDefaultIoResolverBase : public glslang::TIoMapResolver {
|
||||
public:
|
||||
TDefaultIoResolverBase(const TIntermediate& intermediate);
|
||||
typedef std::vector<int> TSlotSet;
|
||||
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
|
||||
|
||||
// grow the reflection stage by stage
|
||||
void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {}
|
||||
void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {}
|
||||
void beginNotifications(EShLanguage) override {}
|
||||
void endNotifications(EShLanguage) override {}
|
||||
void beginResolve(EShLanguage) override {}
|
||||
void endResolve(EShLanguage) override {}
|
||||
void beginCollect(EShLanguage) override {}
|
||||
void endCollect(EShLanguage) override {}
|
||||
void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
||||
void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
||||
int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
|
||||
const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
|
||||
virtual TResourceType getResourceType(const glslang::TType& type) = 0;
|
||||
bool doAutoBindingMapping() const;
|
||||
bool doAutoLocationMapping() const;
|
||||
TSlotSet::iterator findSlot(int set, int slot);
|
||||
bool checkEmpty(int set, int slot);
|
||||
bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
|
||||
int reserveSlot(int set, int slot, int size = 1);
|
||||
int getFreeSlot(int set, int base, int size = 1);
|
||||
int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||
int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
|
||||
int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||
int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||
void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
|
||||
if (stage < EShLangCount) {
|
||||
stageMask[stage] = true;
|
||||
stageIntermediates[stage] = &stageIntermediate;
|
||||
}
|
||||
}
|
||||
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
|
||||
|
||||
TSlotSetMap slots;
|
||||
bool hasError = false;
|
||||
|
||||
protected:
|
||||
TDefaultIoResolverBase(TDefaultIoResolverBase&);
|
||||
TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
|
||||
const TIntermediate& intermediate;
|
||||
int nextUniformLocation;
|
||||
int nextInputLocation;
|
||||
int nextOutputLocation;
|
||||
bool stageMask[EShLangCount + 1];
|
||||
const TIntermediate* stageIntermediates[EShLangCount];
|
||||
|
||||
// Return descriptor set specific base if there is one, and the generic base otherwise.
|
||||
int selectBaseBinding(int base, int descriptorSetBase) const {
|
||||
return descriptorSetBase != -1 ? descriptorSetBase : base;
|
||||
}
|
||||
|
||||
static int getLayoutSet(const glslang::TType& type) {
|
||||
if (type.getQualifier().hasSet())
|
||||
return type.getQualifier().layoutSet;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool isSamplerType(const glslang::TType& type) {
|
||||
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler();
|
||||
}
|
||||
|
||||
static bool isTextureType(const glslang::TType& type) {
|
||||
return (type.getBasicType() == glslang::EbtSampler &&
|
||||
(type.getSampler().isTexture() || type.getSampler().isSubpass()));
|
||||
}
|
||||
|
||||
static bool isUboType(const glslang::TType& type) {
|
||||
return type.getQualifier().storage == EvqUniform;
|
||||
}
|
||||
|
||||
static bool isImageType(const glslang::TType& type) {
|
||||
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage();
|
||||
}
|
||||
|
||||
static bool isSsboType(const glslang::TType& type) {
|
||||
return type.getQualifier().storage == EvqBuffer;
|
||||
}
|
||||
|
||||
// Return true if this is a SRV (shader resource view) type:
|
||||
static bool isSrvType(const glslang::TType& type) {
|
||||
return isTextureType(type) || type.getQualifier().storage == EvqBuffer;
|
||||
}
|
||||
|
||||
// Return true if this is a UAV (unordered access view) type:
|
||||
static bool isUavType(const glslang::TType& type) {
|
||||
if (type.getQualifier().isReadOnly())
|
||||
return false;
|
||||
return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) ||
|
||||
(type.getQualifier().storage == EvqBuffer);
|
||||
}
|
||||
};
|
||||
|
||||
// Default I/O resolver for OpenGL
|
||||
struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
|
||||
public:
|
||||
typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
|
||||
typedef std::map<int, TVarSlotMap> TSlotMap; // <resourceKey, TVarSlotMap>
|
||||
TDefaultGlslIoResolver(const TIntermediate& intermediate);
|
||||
bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
|
||||
TResourceType getResourceType(const glslang::TType& type) override;
|
||||
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
|
||||
int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||
int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||
void beginResolve(EShLanguage /*stage*/) override;
|
||||
void endResolve(EShLanguage stage) override;
|
||||
void beginCollect(EShLanguage) override;
|
||||
void endCollect(EShLanguage) override;
|
||||
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||
void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||
// in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
|
||||
// We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
|
||||
// if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
|
||||
// Note: both stage and type must less then 0xffff.
|
||||
int buildStorageKey(EShLanguage stage, TStorageQualifier type) {
|
||||
assert(static_cast<uint32_t>(stage) <= 0x0000ffff && static_cast<uint32_t>(type) <= 0x0000ffff);
|
||||
return (stage << 16) | type;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Use for mark pre stage, to get more interface symbol information.
|
||||
EShLanguage preStage;
|
||||
// Use for mark current shader stage for resolver
|
||||
EShLanguage currentStage;
|
||||
// Slot map for storage resource(location of uniform and interface symbol) It's a program share slot
|
||||
TSlotMap resourceSlotMap;
|
||||
// Slot map for other resource(image, ubo, ssbo), It's a program share slot.
|
||||
TSlotMap storageSlotMap;
|
||||
};
|
||||
|
||||
typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
|
||||
|
||||
// override function "operator=", if a vector<const _Kty, _Ty> being sort,
|
||||
// when use vc++, the sort function will call :
|
||||
// pair& operator=(const pair<_Other1, _Other2>& _Right)
|
||||
// {
|
||||
// first = _Right.first;
|
||||
// second = _Right.second;
|
||||
// return (*this);
|
||||
// }
|
||||
// that will make a const type handing on left.
|
||||
// override this function can avoid a compiler error.
|
||||
// In the future, if the vc++ compiler can handle such a situation,
|
||||
// this part of the code will be removed.
|
||||
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
|
||||
TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
|
||||
TVarLivePair& operator=(const TVarLivePair& _Right) {
|
||||
const_cast<TString&>(first) = _Right.first;
|
||||
second = _Right.second;
|
||||
return (*this);
|
||||
}
|
||||
TVarLivePair(const TVarLivePair& src) : pair(src) { }
|
||||
};
|
||||
typedef std::vector<TVarLivePair> TVarLiveVector;
|
||||
|
||||
// I/O mapper
|
||||
class TIoMapper {
|
||||
public:
|
||||
TIoMapper() {}
|
||||
virtual ~TIoMapper() {}
|
||||
// grow the reflection stage by stage
|
||||
bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*);
|
||||
bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; }
|
||||
};
|
||||
|
||||
// I/O mapper for OpenGL
|
||||
class TGlslIoMapper : public TIoMapper {
|
||||
public:
|
||||
TGlslIoMapper() {
|
||||
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
|
||||
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
|
||||
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
|
||||
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
|
||||
profile = ENoProfile;
|
||||
version = 0;
|
||||
}
|
||||
virtual ~TGlslIoMapper() {
|
||||
for (size_t stage = 0; stage < EShLangCount; stage++) {
|
||||
if (inVarMaps[stage] != nullptr) {
|
||||
delete inVarMaps[stage];
|
||||
inVarMaps[stage] = nullptr;
|
||||
}
|
||||
if (outVarMaps[stage] != nullptr) {
|
||||
delete outVarMaps[stage];
|
||||
outVarMaps[stage] = nullptr;
|
||||
}
|
||||
if (uniformVarMap[stage] != nullptr) {
|
||||
delete uniformVarMap[stage];
|
||||
uniformVarMap[stage] = nullptr;
|
||||
}
|
||||
if (intermediates[stage] != nullptr)
|
||||
intermediates[stage] = nullptr;
|
||||
}
|
||||
}
|
||||
// grow the reflection stage by stage
|
||||
bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
|
||||
bool doMap(TIoMapResolver*, TInfoSink&) override;
|
||||
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount],
|
||||
*uniformVarMap[EShLangCount];
|
||||
TIntermediate* intermediates[EShLangCount];
|
||||
bool hadError = false;
|
||||
EProfile profile;
|
||||
int version;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _IOMAPPER_INCLUDED
|
||||
|
||||
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,245 @@
|
|||
//
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
// Copyright (C) 2017 ARM Limited.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
// This is implemented in Versions.cpp
|
||||
|
||||
#ifndef _PARSE_VERSIONS_INCLUDED_
|
||||
#define _PARSE_VERSIONS_INCLUDED_
|
||||
|
||||
#include "../Public/ShaderLang.h"
|
||||
#include "../Include/InfoSink.h"
|
||||
#include "Scan.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// Base class for parse helpers.
|
||||
// This just has version-related information and checking.
|
||||
// This class should be sufficient for preprocessing.
|
||||
//
|
||||
class TParseVersions {
|
||||
public:
|
||||
TParseVersions(TIntermediate& interm, int version, EProfile profile,
|
||||
const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
|
||||
bool forwardCompatible, EShMessages messages)
|
||||
:
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
forwardCompatible(forwardCompatible),
|
||||
profile(profile),
|
||||
#endif
|
||||
infoSink(infoSink), version(version),
|
||||
language(language),
|
||||
spvVersion(spvVersion),
|
||||
intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { }
|
||||
virtual ~TParseVersions() { }
|
||||
void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc);
|
||||
void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
|
||||
#ifdef GLSLANG_WEB
|
||||
const EProfile profile = EEsProfile;
|
||||
bool isEsProfile() const { return true; }
|
||||
void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
|
||||
{
|
||||
if (! (EEsProfile & profileMask))
|
||||
error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
|
||||
}
|
||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
|
||||
const char* const extensions[], const char* featureDesc)
|
||||
{
|
||||
if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion))
|
||||
error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
|
||||
}
|
||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
|
||||
const char* featureDesc)
|
||||
{
|
||||
profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
|
||||
}
|
||||
void initializeExtensionBehavior() { }
|
||||
void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { }
|
||||
void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { }
|
||||
void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
||||
const char* featureDesc) { }
|
||||
void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
||||
const char* featureDesc) { }
|
||||
TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; }
|
||||
bool extensionTurnedOn(const char* const extension) { return false; }
|
||||
bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; }
|
||||
void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
|
||||
void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
|
||||
void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
|
||||
void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior) { }
|
||||
void fullIntegerCheck(const TSourceLoc&, const char* op) { }
|
||||
void doubleCheck(const TSourceLoc&, const char* op) { }
|
||||
bool float16Arithmetic() { return false; }
|
||||
void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
|
||||
bool int16Arithmetic() { return false; }
|
||||
void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
|
||||
bool int8Arithmetic() { return false; }
|
||||
void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
|
||||
void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
|
||||
void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
|
||||
void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
|
||||
bool relaxedErrors() const { return false; }
|
||||
bool suppressWarnings() const { return true; }
|
||||
bool isForwardCompatible() const { return false; }
|
||||
#else
|
||||
#ifdef GLSLANG_ANGLE
|
||||
const bool forwardCompatible = true;
|
||||
const EProfile profile = ECoreProfile;
|
||||
#else
|
||||
bool forwardCompatible; // true if errors are to be given for use of deprecated features
|
||||
EProfile profile; // the declared profile in the shader (core by default)
|
||||
#endif
|
||||
bool isEsProfile() const { return profile == EEsProfile; }
|
||||
void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc);
|
||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
|
||||
const char* const extensions[], const char* featureDesc);
|
||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
|
||||
const char* featureDesc);
|
||||
virtual void initializeExtensionBehavior();
|
||||
virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
|
||||
virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
|
||||
virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
||||
const char* featureDesc);
|
||||
virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
||||
const char* featureDesc);
|
||||
virtual TExtensionBehavior getExtensionBehavior(const char*);
|
||||
virtual bool extensionTurnedOn(const char* const extension);
|
||||
virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
|
||||
virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
|
||||
virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
|
||||
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
||||
const char* featureDesc);
|
||||
virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
|
||||
virtual void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior);
|
||||
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
|
||||
|
||||
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
|
||||
virtual void doubleCheck(const TSourceLoc&, const char* op);
|
||||
virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual bool float16Arithmetic();
|
||||
virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
|
||||
virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual bool int16Arithmetic();
|
||||
virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
|
||||
virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual bool int8Arithmetic();
|
||||
virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
|
||||
virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
||||
virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false);
|
||||
bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }
|
||||
bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
|
||||
bool isForwardCompatible() const { return forwardCompatible; }
|
||||
#endif // GLSLANG_WEB
|
||||
virtual void spvRemoved(const TSourceLoc&, const char* op);
|
||||
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
|
||||
virtual void requireVulkan(const TSourceLoc&, const char* op);
|
||||
virtual void requireSpv(const TSourceLoc&, const char* op);
|
||||
virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version);
|
||||
|
||||
|
||||
#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
|
||||
void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) { addError(); }
|
||||
void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) { }
|
||||
void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) { addError(); }
|
||||
void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) { }
|
||||
#else
|
||||
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) = 0;
|
||||
virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) = 0;
|
||||
virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) = 0;
|
||||
virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, ...) = 0;
|
||||
#endif
|
||||
|
||||
void addError() { ++numErrors; }
|
||||
int getNumErrors() const { return numErrors; }
|
||||
|
||||
void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
|
||||
TInputScanner* getScanner() const { return currentScanner; }
|
||||
const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
|
||||
void setCurrentLine(int line) { currentScanner->setLine(line); }
|
||||
void setCurrentColumn(int col) { currentScanner->setColumn(col); }
|
||||
void setCurrentSourceName(const char* name) { currentScanner->setFile(name); }
|
||||
void setCurrentString(int string) { currentScanner->setString(string); }
|
||||
|
||||
void getPreamble(std::string&);
|
||||
#ifdef ENABLE_HLSL
|
||||
bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; }
|
||||
bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; }
|
||||
bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; }
|
||||
#else
|
||||
bool isReadingHLSL() const { return false; }
|
||||
#endif
|
||||
|
||||
TInfoSink& infoSink;
|
||||
|
||||
// compilation mode
|
||||
int version; // version, updated by #version in the shader
|
||||
EShLanguage language; // really the stage
|
||||
SpvVersion spvVersion;
|
||||
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
|
||||
|
||||
protected:
|
||||
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is
|
||||
TMap<TString, unsigned int> extensionMinSpv; // for each extension string, store minimum spirv required
|
||||
EShMessages messages; // errors/warnings/rule-sets
|
||||
int numErrors; // number of compile-time errors encountered
|
||||
TInputScanner* currentScanner;
|
||||
|
||||
private:
|
||||
explicit TParseVersions(const TParseVersions&);
|
||||
TParseVersions& operator=(const TParseVersions&);
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _PARSE_VERSIONS_INCLUDED_
|
||||
|
|
@ -0,0 +1,703 @@
|
|||
//
|
||||
// Copyright (C) 2013 LunarG, Inc.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
/****************************************************************************\
|
||||
Copyright (c) 2002, NVIDIA Corporation.
|
||||
|
||||
NVIDIA Corporation("NVIDIA") supplies this software to you in
|
||||
consideration of your agreement to the following terms, and your use,
|
||||
installation, modification or redistribution of this NVIDIA software
|
||||
constitutes acceptance of these terms. If you do not agree with these
|
||||
terms, please do not use, install, modify or redistribute this NVIDIA
|
||||
software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, NVIDIA grants you a personal, non-exclusive
|
||||
license, under NVIDIA's copyrights in this original NVIDIA software (the
|
||||
"NVIDIA Software"), to use, reproduce, modify and redistribute the
|
||||
NVIDIA Software, with or without modifications, in source and/or binary
|
||||
forms; provided that if you redistribute the NVIDIA Software, you must
|
||||
retain the copyright notice of NVIDIA, this notice and the following
|
||||
text and disclaimers in all such redistributions of the NVIDIA Software.
|
||||
Neither the name, trademarks, service marks nor logos of NVIDIA
|
||||
Corporation may be used to endorse or promote products derived from the
|
||||
NVIDIA Software without specific prior written permission from NVIDIA.
|
||||
Except as expressly stated in this notice, no other rights or licenses
|
||||
express or implied, are granted by NVIDIA herein, including but not
|
||||
limited to any patent rights that may be infringed by your derivative
|
||||
works or by other works in which the NVIDIA Software may be
|
||||
incorporated. No hardware is licensed hereunder.
|
||||
|
||||
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
|
||||
PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
||||
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
|
||||
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
|
||||
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
|
||||
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\****************************************************************************/
|
||||
|
||||
#ifndef PPCONTEXT_H
|
||||
#define PPCONTEXT_H
|
||||
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
|
||||
#include "../ParseHelper.h"
|
||||
#include "PpTokens.h"
|
||||
|
||||
/* windows only pragma */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TPpToken {
|
||||
public:
|
||||
TPpToken() { clear(); }
|
||||
void clear()
|
||||
{
|
||||
space = false;
|
||||
i64val = 0;
|
||||
loc.init();
|
||||
name[0] = 0;
|
||||
}
|
||||
|
||||
// Used for comparing macro definitions, so checks what is relevant for that.
|
||||
bool operator==(const TPpToken& right) const
|
||||
{
|
||||
return space == right.space &&
|
||||
ival == right.ival && dval == right.dval && i64val == right.i64val &&
|
||||
strncmp(name, right.name, MaxTokenLength) == 0;
|
||||
}
|
||||
bool operator!=(const TPpToken& right) const { return ! operator==(right); }
|
||||
|
||||
TSourceLoc loc;
|
||||
// True if a space (for white space or a removed comment) should also be
|
||||
// recognized, in front of the token returned:
|
||||
bool space;
|
||||
// Numeric value of the token:
|
||||
union {
|
||||
int ival;
|
||||
double dval;
|
||||
long long i64val;
|
||||
};
|
||||
// Text string of the token:
|
||||
char name[MaxTokenLength + 1];
|
||||
};
|
||||
|
||||
class TStringAtomMap {
|
||||
//
|
||||
// Implementation is in PpAtom.cpp
|
||||
//
|
||||
// Maintain a bi-directional mapping between relevant preprocessor strings and
|
||||
// "atoms" which a unique integers (small, contiguous, not hash-like) per string.
|
||||
//
|
||||
public:
|
||||
TStringAtomMap();
|
||||
|
||||
// Map string -> atom.
|
||||
// Return 0 if no existing string.
|
||||
int getAtom(const char* s) const
|
||||
{
|
||||
auto it = atomMap.find(s);
|
||||
return it == atomMap.end() ? 0 : it->second;
|
||||
}
|
||||
|
||||
// Map a new or existing string -> atom, inventing a new atom if necessary.
|
||||
int getAddAtom(const char* s)
|
||||
{
|
||||
int atom = getAtom(s);
|
||||
if (atom == 0) {
|
||||
atom = nextAtom++;
|
||||
addAtomFixed(s, atom);
|
||||
}
|
||||
return atom;
|
||||
}
|
||||
|
||||
// Map atom -> string.
|
||||
const char* getString(int atom) const { return stringMap[atom]->c_str(); }
|
||||
|
||||
protected:
|
||||
TStringAtomMap(TStringAtomMap&);
|
||||
TStringAtomMap& operator=(TStringAtomMap&);
|
||||
|
||||
TUnorderedMap<TString, int> atomMap;
|
||||
TVector<const TString*> stringMap; // these point into the TString in atomMap
|
||||
int nextAtom;
|
||||
|
||||
// Bad source characters can lead to bad atoms, so gracefully handle those by
|
||||
// pre-filling the table with them (to avoid if tests later).
|
||||
TString badToken;
|
||||
|
||||
// Add bi-directional mappings:
|
||||
// - string -> atom
|
||||
// - atom -> string
|
||||
void addAtomFixed(const char* s, int atom)
|
||||
{
|
||||
auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
|
||||
if (stringMap.size() < (size_t)atom + 1)
|
||||
stringMap.resize(atom + 100, &badToken);
|
||||
stringMap[atom] = &it->first;
|
||||
}
|
||||
};
|
||||
|
||||
class TInputScanner;
|
||||
|
||||
enum MacroExpandResult {
|
||||
MacroExpandNotStarted, // macro not expanded, which might not be an error
|
||||
MacroExpandError, // a clear error occurred while expanding, no expansion
|
||||
MacroExpandStarted, // macro expansion process has started
|
||||
MacroExpandUndef // macro is undefined and will be expanded
|
||||
};
|
||||
|
||||
// This class is the result of turning a huge pile of C code communicating through globals
|
||||
// into a class. This was done to allowing instancing to attain thread safety.
|
||||
// Don't expect too much in terms of OO design.
|
||||
class TPpContext {
|
||||
public:
|
||||
TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&);
|
||||
virtual ~TPpContext();
|
||||
|
||||
void setPreamble(const char* preamble, size_t length);
|
||||
|
||||
int tokenize(TPpToken& ppToken);
|
||||
int tokenPaste(int token, TPpToken&);
|
||||
|
||||
class tInput {
|
||||
public:
|
||||
tInput(TPpContext* p) : done(false), pp(p) { }
|
||||
virtual ~tInput() { }
|
||||
|
||||
virtual int scan(TPpToken*) = 0;
|
||||
virtual int getch() = 0;
|
||||
virtual void ungetch() = 0;
|
||||
virtual bool peekPasting() { return false; } // true when about to see ##
|
||||
virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste
|
||||
virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
|
||||
virtual bool isMacroInput() { return false; }
|
||||
|
||||
// Will be called when we start reading tokens from this instance
|
||||
virtual void notifyActivated() {}
|
||||
// Will be called when we do not read tokens from this instance anymore
|
||||
virtual void notifyDeleted() {}
|
||||
protected:
|
||||
bool done;
|
||||
TPpContext* pp;
|
||||
};
|
||||
|
||||
void setInput(TInputScanner& input, bool versionWillBeError);
|
||||
|
||||
void pushInput(tInput* in)
|
||||
{
|
||||
inputStack.push_back(in);
|
||||
in->notifyActivated();
|
||||
}
|
||||
void popInput()
|
||||
{
|
||||
inputStack.back()->notifyDeleted();
|
||||
delete inputStack.back();
|
||||
inputStack.pop_back();
|
||||
}
|
||||
|
||||
//
|
||||
// From PpTokens.cpp
|
||||
//
|
||||
|
||||
// Capture the needed parts of a token stream for macro recording/playback.
|
||||
class TokenStream {
|
||||
public:
|
||||
// Manage a stream of these 'Token', which capture the relevant parts
|
||||
// of a TPpToken, plus its atom.
|
||||
class Token {
|
||||
public:
|
||||
Token(int atom, const TPpToken& ppToken) :
|
||||
atom(atom),
|
||||
space(ppToken.space),
|
||||
i64val(ppToken.i64val),
|
||||
name(ppToken.name) { }
|
||||
int get(TPpToken& ppToken)
|
||||
{
|
||||
ppToken.clear();
|
||||
ppToken.space = space;
|
||||
ppToken.i64val = i64val;
|
||||
snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str());
|
||||
return atom;
|
||||
}
|
||||
bool isAtom(int a) const { return atom == a; }
|
||||
int getAtom() const { return atom; }
|
||||
bool nonSpaced() const { return !space; }
|
||||
protected:
|
||||
Token() {}
|
||||
int atom;
|
||||
bool space; // did a space precede the token?
|
||||
long long i64val;
|
||||
TString name;
|
||||
};
|
||||
|
||||
TokenStream() : currentPos(0) { }
|
||||
|
||||
void putToken(int token, TPpToken* ppToken);
|
||||
bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); }
|
||||
bool peekContinuedPasting(int atom)
|
||||
{
|
||||
// This is basically necessary because, for example, the PP
|
||||
// tokenizer only accepts valid numeric-literals plus suffixes, so
|
||||
// separates numeric-literals plus bad suffix into two tokens, which
|
||||
// should get both pasted together as one token when token pasting.
|
||||
//
|
||||
// The following code is a bit more generalized than the above example.
|
||||
if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) {
|
||||
switch(stream[currentPos].getAtom()) {
|
||||
case PpAtomConstInt:
|
||||
case PpAtomConstUint:
|
||||
case PpAtomConstInt64:
|
||||
case PpAtomConstUint64:
|
||||
case PpAtomConstInt16:
|
||||
case PpAtomConstUint16:
|
||||
case PpAtomConstFloat:
|
||||
case PpAtomConstDouble:
|
||||
case PpAtomConstFloat16:
|
||||
case PpAtomConstString:
|
||||
case PpAtomIdentifier:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
int getToken(TParseContextBase&, TPpToken*);
|
||||
bool atEnd() { return currentPos >= stream.size(); }
|
||||
bool peekTokenizedPasting(bool lastTokenPastes);
|
||||
bool peekUntokenizedPasting();
|
||||
void reset() { currentPos = 0; }
|
||||
|
||||
protected:
|
||||
TVector<Token> stream;
|
||||
size_t currentPos;
|
||||
};
|
||||
|
||||
//
|
||||
// From Pp.cpp
|
||||
//
|
||||
|
||||
struct MacroSymbol {
|
||||
MacroSymbol() : functionLike(0), busy(0), undef(0) { }
|
||||
TVector<int> args;
|
||||
TokenStream body;
|
||||
unsigned functionLike : 1; // 0 means object-like, 1 means function-like
|
||||
unsigned busy : 1;
|
||||
unsigned undef : 1;
|
||||
};
|
||||
|
||||
typedef TMap<int, MacroSymbol> TSymbolMap;
|
||||
TSymbolMap macroDefs; // map atoms to macro definitions
|
||||
MacroSymbol* lookupMacroDef(int atom)
|
||||
{
|
||||
auto existingMacroIt = macroDefs.find(atom);
|
||||
return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second);
|
||||
}
|
||||
void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; }
|
||||
|
||||
protected:
|
||||
TPpContext(TPpContext&);
|
||||
TPpContext& operator=(TPpContext&);
|
||||
|
||||
TStringAtomMap atomStrings;
|
||||
char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble
|
||||
int preambleLength;
|
||||
char** strings; // official strings of shader, starting a string 0 line 1
|
||||
size_t* lengths;
|
||||
int numStrings; // how many official strings there are
|
||||
int currentString; // which string we're currently parsing (-1 for preamble)
|
||||
|
||||
// Scanner data:
|
||||
int previous_token;
|
||||
TParseContextBase& parseContext;
|
||||
|
||||
// Get the next token from *stack* of input sources, popping input sources
|
||||
// that are out of tokens, down until an input source is found that has a token.
|
||||
// Return EndOfInput when there are no more tokens to be found by doing this.
|
||||
int scanToken(TPpToken* ppToken)
|
||||
{
|
||||
int token = EndOfInput;
|
||||
|
||||
while (! inputStack.empty()) {
|
||||
token = inputStack.back()->scan(ppToken);
|
||||
if (token != EndOfInput || inputStack.empty())
|
||||
break;
|
||||
popInput();
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
int getChar() { return inputStack.back()->getch(); }
|
||||
void ungetChar() { inputStack.back()->ungetch(); }
|
||||
bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
|
||||
bool peekContinuedPasting(int a)
|
||||
{
|
||||
return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a);
|
||||
}
|
||||
bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
|
||||
bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
|
||||
|
||||
static const int maxIfNesting = 65;
|
||||
|
||||
int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
|
||||
bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth
|
||||
int elsetracker; // #if-#else and #endif constructs...Counter.
|
||||
|
||||
class tMacroInput : public tInput {
|
||||
public:
|
||||
tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { }
|
||||
virtual ~tMacroInput()
|
||||
{
|
||||
for (size_t i = 0; i < args.size(); ++i)
|
||||
delete args[i];
|
||||
for (size_t i = 0; i < expandedArgs.size(); ++i)
|
||||
delete expandedArgs[i];
|
||||
}
|
||||
|
||||
virtual int scan(TPpToken*) override;
|
||||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
bool peekPasting() override { return prepaste; }
|
||||
bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); }
|
||||
bool endOfReplacementList() override { return mac->body.atEnd(); }
|
||||
bool isMacroInput() override { return true; }
|
||||
|
||||
MacroSymbol *mac;
|
||||
TVector<TokenStream*> args;
|
||||
TVector<TokenStream*> expandedArgs;
|
||||
|
||||
protected:
|
||||
bool prepaste; // true if we are just before ##
|
||||
bool postpaste; // true if we are right after ##
|
||||
};
|
||||
|
||||
class tMarkerInput : public tInput {
|
||||
public:
|
||||
tMarkerInput(TPpContext* pp) : tInput(pp) { }
|
||||
virtual int scan(TPpToken*) override
|
||||
{
|
||||
if (done)
|
||||
return EndOfInput;
|
||||
done = true;
|
||||
|
||||
return marker;
|
||||
}
|
||||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
static const int marker = -3;
|
||||
};
|
||||
|
||||
class tZeroInput : public tInput {
|
||||
public:
|
||||
tZeroInput(TPpContext* pp) : tInput(pp) { }
|
||||
virtual int scan(TPpToken*) override;
|
||||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
};
|
||||
|
||||
std::vector<tInput*> inputStack;
|
||||
bool errorOnVersion;
|
||||
bool versionSeen;
|
||||
|
||||
//
|
||||
// from Pp.cpp
|
||||
//
|
||||
|
||||
// Used to obtain #include content.
|
||||
TShader::Includer& includer;
|
||||
|
||||
int CPPdefine(TPpToken * ppToken);
|
||||
int CPPundef(TPpToken * ppToken);
|
||||
int CPPelse(int matchelse, TPpToken * ppToken);
|
||||
int extraTokenCheck(int atom, TPpToken* ppToken, int token);
|
||||
int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
|
||||
int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
|
||||
int CPPif (TPpToken * ppToken);
|
||||
int CPPifdef(int defined, TPpToken * ppToken);
|
||||
int CPPinclude(TPpToken * ppToken);
|
||||
int CPPline(TPpToken * ppToken);
|
||||
int CPPerror(TPpToken * ppToken);
|
||||
int CPPpragma(TPpToken * ppToken);
|
||||
int CPPversion(TPpToken * ppToken);
|
||||
int CPPextension(TPpToken * ppToken);
|
||||
int readCPPline(TPpToken * ppToken);
|
||||
int scanHeaderName(TPpToken* ppToken, char delimit);
|
||||
TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
|
||||
MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
|
||||
|
||||
//
|
||||
// From PpTokens.cpp
|
||||
//
|
||||
void pushTokenStreamInput(TokenStream&, bool pasting = false);
|
||||
void UngetToken(int token, TPpToken*);
|
||||
|
||||
class tTokenInput : public tInput {
|
||||
public:
|
||||
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) :
|
||||
tInput(pp),
|
||||
tokens(t),
|
||||
lastTokenPastes(prepasting) { }
|
||||
virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
|
||||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
|
||||
bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); }
|
||||
protected:
|
||||
TokenStream* tokens;
|
||||
bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
|
||||
};
|
||||
|
||||
class tUngotTokenInput : public tInput {
|
||||
public:
|
||||
tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
|
||||
virtual int scan(TPpToken *) override;
|
||||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
protected:
|
||||
int token;
|
||||
TPpToken lval;
|
||||
};
|
||||
|
||||
//
|
||||
// From PpScanner.cpp
|
||||
//
|
||||
class tStringInput : public tInput {
|
||||
public:
|
||||
tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
|
||||
virtual int scan(TPpToken*) override;
|
||||
|
||||
// Scanner used to get source stream characters.
|
||||
// - Escaped newlines are handled here, invisibly to the caller.
|
||||
// - All forms of newline are handled, and turned into just a '\n'.
|
||||
int getch() override
|
||||
{
|
||||
int ch = input->get();
|
||||
|
||||
if (ch == '\\') {
|
||||
// Move past escaped newlines, as many as sequentially exist
|
||||
do {
|
||||
if (input->peek() == '\r' || input->peek() == '\n') {
|
||||
bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
|
||||
if (! allowed && pp->inComment)
|
||||
return '\\';
|
||||
|
||||
// escape one newline now
|
||||
ch = input->get();
|
||||
int nextch = input->get();
|
||||
if (ch == '\r' && nextch == '\n')
|
||||
ch = input->get();
|
||||
else
|
||||
ch = nextch;
|
||||
} else
|
||||
return '\\';
|
||||
} while (ch == '\\');
|
||||
}
|
||||
|
||||
// handle any non-escaped newline
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
if (ch == '\r' && input->peek() == '\n')
|
||||
input->get();
|
||||
return '\n';
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
// Scanner used to backup the source stream characters. Newlines are
|
||||
// handled here, invisibly to the caller, meaning have to undo exactly
|
||||
// what getch() above does (e.g., don't leave things in the middle of a
|
||||
// sequence of escaped newlines).
|
||||
void ungetch() override
|
||||
{
|
||||
input->unget();
|
||||
|
||||
do {
|
||||
int ch = input->peek();
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
if (ch == '\n') {
|
||||
// correct for two-character newline
|
||||
input->unget();
|
||||
if (input->peek() != '\r')
|
||||
input->get();
|
||||
}
|
||||
// now in front of a complete newline, move past an escape character
|
||||
input->unget();
|
||||
if (input->peek() == '\\')
|
||||
input->unget();
|
||||
else {
|
||||
input->get();
|
||||
break;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
protected:
|
||||
TInputScanner* input;
|
||||
};
|
||||
|
||||
// Holds a reference to included file data, as well as a
|
||||
// prologue and an epilogue string. This can be scanned using the tInput
|
||||
// interface and acts as a single source string.
|
||||
class TokenizableIncludeFile : public tInput {
|
||||
public:
|
||||
// Copies prologue and epilogue. The includedFile must remain valid
|
||||
// until this TokenizableIncludeFile is no longer used.
|
||||
TokenizableIncludeFile(const TSourceLoc& startLoc,
|
||||
const std::string& prologue,
|
||||
TShader::Includer::IncludeResult* includedFile,
|
||||
const std::string& epilogue,
|
||||
TPpContext* pp)
|
||||
: tInput(pp),
|
||||
prologue_(prologue),
|
||||
epilogue_(epilogue),
|
||||
includedFile_(includedFile),
|
||||
scanner(3, strings, lengths, nullptr, 0, 0, true),
|
||||
prevScanner(nullptr),
|
||||
stringInput(pp, scanner)
|
||||
{
|
||||
strings[0] = prologue_.data();
|
||||
strings[1] = includedFile_->headerData;
|
||||
strings[2] = epilogue_.data();
|
||||
|
||||
lengths[0] = prologue_.size();
|
||||
lengths[1] = includedFile_->headerLength;
|
||||
lengths[2] = epilogue_.size();
|
||||
|
||||
scanner.setLine(startLoc.line);
|
||||
scanner.setString(startLoc.string);
|
||||
|
||||
scanner.setFile(startLoc.getFilenameStr(), 0);
|
||||
scanner.setFile(startLoc.getFilenameStr(), 1);
|
||||
scanner.setFile(startLoc.getFilenameStr(), 2);
|
||||
}
|
||||
|
||||
// tInput methods:
|
||||
int scan(TPpToken* t) override { return stringInput.scan(t); }
|
||||
int getch() override { return stringInput.getch(); }
|
||||
void ungetch() override { stringInput.ungetch(); }
|
||||
|
||||
void notifyActivated() override
|
||||
{
|
||||
prevScanner = pp->parseContext.getScanner();
|
||||
pp->parseContext.setScanner(&scanner);
|
||||
pp->push_include(includedFile_);
|
||||
}
|
||||
|
||||
void notifyDeleted() override
|
||||
{
|
||||
pp->parseContext.setScanner(prevScanner);
|
||||
pp->pop_include();
|
||||
}
|
||||
|
||||
private:
|
||||
TokenizableIncludeFile& operator=(const TokenizableIncludeFile&);
|
||||
|
||||
// Stores the prologue for this string.
|
||||
const std::string prologue_;
|
||||
|
||||
// Stores the epilogue for this string.
|
||||
const std::string epilogue_;
|
||||
|
||||
// Points to the IncludeResult that this TokenizableIncludeFile represents.
|
||||
TShader::Includer::IncludeResult* includedFile_;
|
||||
|
||||
// Will point to prologue_, includedFile_->headerData and epilogue_
|
||||
// This is passed to scanner constructor.
|
||||
// These do not own the storage and it must remain valid until this
|
||||
// object has been destroyed.
|
||||
const char* strings[3];
|
||||
// Length of str_, passed to scanner constructor.
|
||||
size_t lengths[3];
|
||||
// Scans over str_.
|
||||
TInputScanner scanner;
|
||||
// The previous effective scanner before the scanner in this instance
|
||||
// has been activated.
|
||||
TInputScanner* prevScanner;
|
||||
// Delegate object implementing the tInput interface.
|
||||
tStringInput stringInput;
|
||||
};
|
||||
|
||||
int ScanFromString(char* s);
|
||||
void missingEndifCheck();
|
||||
int lFloatConst(int len, int ch, TPpToken* ppToken);
|
||||
int characterLiteral(TPpToken* ppToken);
|
||||
|
||||
void push_include(TShader::Includer::IncludeResult* result)
|
||||
{
|
||||
currentSourceFile = result->headerName;
|
||||
includeStack.push(result);
|
||||
}
|
||||
|
||||
void pop_include()
|
||||
{
|
||||
TShader::Includer::IncludeResult* include = includeStack.top();
|
||||
includeStack.pop();
|
||||
includer.releaseInclude(include);
|
||||
if (includeStack.empty()) {
|
||||
currentSourceFile = rootFileName;
|
||||
} else {
|
||||
currentSourceFile = includeStack.top()->headerName;
|
||||
}
|
||||
}
|
||||
|
||||
bool inComment;
|
||||
std::string rootFileName;
|
||||
std::stack<TShader::Includer::IncludeResult*> includeStack;
|
||||
std::string currentSourceFile;
|
||||
|
||||
std::istringstream strtodStream;
|
||||
bool disableEscapeSequences;
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // PPCONTEXT_H
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
/****************************************************************************\
|
||||
Copyright (c) 2002, NVIDIA Corporation.
|
||||
|
||||
NVIDIA Corporation("NVIDIA") supplies this software to you in
|
||||
consideration of your agreement to the following terms, and your use,
|
||||
installation, modification or redistribution of this NVIDIA software
|
||||
constitutes acceptance of these terms. If you do not agree with these
|
||||
terms, please do not use, install, modify or redistribute this NVIDIA
|
||||
software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, NVIDIA grants you a personal, non-exclusive
|
||||
license, under NVIDIA's copyrights in this original NVIDIA software (the
|
||||
"NVIDIA Software"), to use, reproduce, modify and redistribute the
|
||||
NVIDIA Software, with or without modifications, in source and/or binary
|
||||
forms; provided that if you redistribute the NVIDIA Software, you must
|
||||
retain the copyright notice of NVIDIA, this notice and the following
|
||||
text and disclaimers in all such redistributions of the NVIDIA Software.
|
||||
Neither the name, trademarks, service marks nor logos of NVIDIA
|
||||
Corporation may be used to endorse or promote products derived from the
|
||||
NVIDIA Software without specific prior written permission from NVIDIA.
|
||||
Except as expressly stated in this notice, no other rights or licenses
|
||||
express or implied, are granted by NVIDIA herein, including but not
|
||||
limited to any patent rights that may be infringed by your derivative
|
||||
works or by other works in which the NVIDIA Software may be
|
||||
incorporated. No hardware is licensed hereunder.
|
||||
|
||||
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
|
||||
PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
||||
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
|
||||
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
|
||||
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
|
||||
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
||||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\****************************************************************************/
|
||||
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// Multi-character tokens
|
||||
enum EFixedAtoms {
|
||||
// single character tokens get their own char value as their token; start here for multi-character tokens
|
||||
PpAtomMaxSingle = 127,
|
||||
|
||||
// replace bad character tokens with this, to avoid accidental aliasing with the below
|
||||
PpAtomBadToken,
|
||||
|
||||
// Operators
|
||||
|
||||
PPAtomAddAssign,
|
||||
PPAtomSubAssign,
|
||||
PPAtomMulAssign,
|
||||
PPAtomDivAssign,
|
||||
PPAtomModAssign,
|
||||
|
||||
PpAtomRight,
|
||||
PpAtomLeft,
|
||||
|
||||
PpAtomRightAssign,
|
||||
PpAtomLeftAssign,
|
||||
PpAtomAndAssign,
|
||||
PpAtomOrAssign,
|
||||
PpAtomXorAssign,
|
||||
|
||||
PpAtomAnd,
|
||||
PpAtomOr,
|
||||
PpAtomXor,
|
||||
|
||||
PpAtomEQ,
|
||||
PpAtomNE,
|
||||
PpAtomGE,
|
||||
PpAtomLE,
|
||||
|
||||
PpAtomDecrement,
|
||||
PpAtomIncrement,
|
||||
|
||||
PpAtomColonColon,
|
||||
|
||||
PpAtomPaste,
|
||||
|
||||
// Constants
|
||||
|
||||
PpAtomConstInt,
|
||||
PpAtomConstUint,
|
||||
PpAtomConstInt64,
|
||||
PpAtomConstUint64,
|
||||
PpAtomConstInt16,
|
||||
PpAtomConstUint16,
|
||||
PpAtomConstFloat,
|
||||
PpAtomConstDouble,
|
||||
PpAtomConstFloat16,
|
||||
PpAtomConstString,
|
||||
|
||||
// Identifiers
|
||||
PpAtomIdentifier,
|
||||
|
||||
// preprocessor "keywords"
|
||||
|
||||
PpAtomDefine,
|
||||
PpAtomUndef,
|
||||
|
||||
PpAtomIf,
|
||||
PpAtomIfdef,
|
||||
PpAtomIfndef,
|
||||
PpAtomElse,
|
||||
PpAtomElif,
|
||||
PpAtomEndif,
|
||||
|
||||
PpAtomLine,
|
||||
PpAtomPragma,
|
||||
PpAtomError,
|
||||
|
||||
// #version ...
|
||||
PpAtomVersion,
|
||||
PpAtomCore,
|
||||
PpAtomCompatibility,
|
||||
PpAtomEs,
|
||||
|
||||
// #extension
|
||||
PpAtomExtension,
|
||||
|
||||
// __LINE__, __FILE__, __VERSION__
|
||||
|
||||
PpAtomLineMacro,
|
||||
PpAtomFileMacro,
|
||||
PpAtomVersionMacro,
|
||||
|
||||
// #include
|
||||
PpAtomInclude,
|
||||
|
||||
PpAtomLast,
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif /* not PARSER_H */
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Copyright (C) 2015-2016 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Visit the nodes in the glslang intermediate tree representation to
|
||||
// propagate 'noContraction' qualifier.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Include/intermediate.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
// Propagates the 'precise' qualifier for objects (objects marked with
|
||||
// 'noContraction' qualifier) from the shader source specified 'precise'
|
||||
// variables to all the involved objects, and add 'noContraction' qualifier for
|
||||
// the involved arithmetic operations.
|
||||
// Note that the same qualifier: 'noContraction' is used in both object nodes
|
||||
// and arithmetic operation nodes, but has different meaning. For object nodes,
|
||||
// 'noContraction' means the object is 'precise'; and for arithmetic operation
|
||||
// nodes, it means the operation should not be contracted.
|
||||
void PropagateNoContraction(const glslang::TIntermediate& intermediate);
|
||||
};
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
//
|
||||
// Copyright (C) 2013-2016 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
|
||||
#ifndef _REFLECTION_INCLUDED
|
||||
#define _REFLECTION_INCLUDED
|
||||
|
||||
#include "../Public/ShaderLang.h"
|
||||
#include "../Include/Types.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
//
|
||||
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
|
||||
//
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TIntermediate;
|
||||
class TIntermAggregate;
|
||||
class TReflectionTraverser;
|
||||
|
||||
// The full reflection database
|
||||
class TReflection {
|
||||
public:
|
||||
TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last)
|
||||
: options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection())
|
||||
{
|
||||
for (int dim=0; dim<3; ++dim)
|
||||
localSize[dim] = 0;
|
||||
}
|
||||
|
||||
virtual ~TReflection() {}
|
||||
|
||||
// grow the reflection stage by stage
|
||||
bool addStage(EShLanguage, const TIntermediate&);
|
||||
|
||||
// for mapping a uniform index to a uniform object's description
|
||||
int getNumUniforms() { return (int)indexToUniform.size(); }
|
||||
const TObjectReflection& getUniform(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)indexToUniform.size())
|
||||
return indexToUniform[i];
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping a block index to the block's description
|
||||
int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); }
|
||||
const TObjectReflection& getUniformBlock(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)indexToUniformBlock.size())
|
||||
return indexToUniformBlock[i];
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping an pipeline input index to the input's description
|
||||
int getNumPipeInputs() { return (int)indexToPipeInput.size(); }
|
||||
const TObjectReflection& getPipeInput(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)indexToPipeInput.size())
|
||||
return indexToPipeInput[i];
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping an pipeline output index to the output's description
|
||||
int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); }
|
||||
const TObjectReflection& getPipeOutput(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)indexToPipeOutput.size())
|
||||
return indexToPipeOutput[i];
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping from an atomic counter to the uniform index
|
||||
int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); }
|
||||
const TObjectReflection& getAtomicCounter(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)atomicCounterUniformIndices.size())
|
||||
return getUniform(atomicCounterUniformIndices[i]);
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping a buffer variable index to a buffer variable object's description
|
||||
int getNumBufferVariables() { return (int)indexToBufferVariable.size(); }
|
||||
const TObjectReflection& getBufferVariable(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)indexToBufferVariable.size())
|
||||
return indexToBufferVariable[i];
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping a storage block index to the storage block's description
|
||||
int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); }
|
||||
const TObjectReflection& getStorageBufferBlock(int i) const
|
||||
{
|
||||
if (i >= 0 && i < (int)indexToBufferBlock.size())
|
||||
return indexToBufferBlock[i];
|
||||
else
|
||||
return badReflection;
|
||||
}
|
||||
|
||||
// for mapping any name to its index (block names, uniform names and input/output names)
|
||||
int getIndex(const char* name) const
|
||||
{
|
||||
TNameToIndex::const_iterator it = nameToIndex.find(name);
|
||||
if (it == nameToIndex.end())
|
||||
return -1;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// see getIndex(const char*)
|
||||
int getIndex(const TString& name) const { return getIndex(name.c_str()); }
|
||||
|
||||
|
||||
// for mapping any name to its index (only pipe input/output names)
|
||||
int getPipeIOIndex(const char* name, const bool inOrOut) const
|
||||
{
|
||||
TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name);
|
||||
if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end()))
|
||||
return -1;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// see gePipeIOIndex(const char*, const bool)
|
||||
int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); }
|
||||
|
||||
// Thread local size
|
||||
unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; }
|
||||
|
||||
void dump();
|
||||
|
||||
protected:
|
||||
friend class glslang::TReflectionTraverser;
|
||||
|
||||
void buildCounterIndices(const TIntermediate&);
|
||||
void buildUniformStageMask(const TIntermediate& intermediate);
|
||||
void buildAttributeReflection(EShLanguage, const TIntermediate&);
|
||||
|
||||
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
|
||||
typedef std::map<std::string, int> TNameToIndex;
|
||||
typedef std::vector<TObjectReflection> TMapIndexToReflection;
|
||||
typedef std::vector<int> TIndices;
|
||||
|
||||
TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage)
|
||||
{
|
||||
if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer)
|
||||
return indexToBufferBlock;
|
||||
return indexToUniformBlock;
|
||||
}
|
||||
TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage)
|
||||
{
|
||||
if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer)
|
||||
return indexToBufferVariable;
|
||||
return indexToUniform;
|
||||
}
|
||||
|
||||
EShReflectionOptions options;
|
||||
|
||||
EShLanguage firstStage;
|
||||
EShLanguage lastStage;
|
||||
|
||||
TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this
|
||||
TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed
|
||||
TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers.
|
||||
TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers.
|
||||
TMapIndexToReflection indexToUniform;
|
||||
TMapIndexToReflection indexToUniformBlock;
|
||||
TMapIndexToReflection indexToBufferVariable;
|
||||
TMapIndexToReflection indexToBufferBlock;
|
||||
TMapIndexToReflection indexToPipeInput;
|
||||
TMapIndexToReflection indexToPipeOutput;
|
||||
TIndices atomicCounterUniformIndices;
|
||||
|
||||
unsigned int localSize[3];
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _REFLECTION_INCLUDED
|
||||
|
||||
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
|
||||
|
|
@ -0,0 +1,970 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2013-2016 LunarG, Inc.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
#ifndef _COMPILER_INTERFACE_INCLUDED_
|
||||
#define _COMPILER_INTERFACE_INCLUDED_
|
||||
|
||||
#include "../Include/ResourceLimits.h"
|
||||
#include "../MachineIndependent/Versions.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define C_DECL __cdecl
|
||||
#else
|
||||
#define C_DECL
|
||||
#endif
|
||||
|
||||
#ifdef GLSLANG_IS_SHARED_LIBRARY
|
||||
#ifdef _WIN32
|
||||
#ifdef GLSLANG_EXPORTING
|
||||
#define GLSLANG_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define GLSLANG_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#elif __GNUC__ >= 4
|
||||
#define GLSLANG_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif // GLSLANG_IS_SHARED_LIBRARY
|
||||
|
||||
#ifndef GLSLANG_EXPORT
|
||||
#define GLSLANG_EXPORT
|
||||
#endif
|
||||
|
||||
//
|
||||
// This is the platform independent interface between an OGL driver
|
||||
// and the shading language compiler/linker.
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// Call before doing any other compiler/linker operations.
|
||||
//
|
||||
// (Call once per process, not once per thread.)
|
||||
//
|
||||
GLSLANG_EXPORT int ShInitialize();
|
||||
|
||||
//
|
||||
// Call this at process shutdown to clean up memory.
|
||||
//
|
||||
GLSLANG_EXPORT int ShFinalize();
|
||||
|
||||
//
|
||||
// Types of languages the compiler can consume.
|
||||
//
|
||||
typedef enum {
|
||||
EShLangVertex,
|
||||
EShLangTessControl,
|
||||
EShLangTessEvaluation,
|
||||
EShLangGeometry,
|
||||
EShLangFragment,
|
||||
EShLangCompute,
|
||||
EShLangRayGen,
|
||||
EShLangRayGenNV = EShLangRayGen,
|
||||
EShLangIntersect,
|
||||
EShLangIntersectNV = EShLangIntersect,
|
||||
EShLangAnyHit,
|
||||
EShLangAnyHitNV = EShLangAnyHit,
|
||||
EShLangClosestHit,
|
||||
EShLangClosestHitNV = EShLangClosestHit,
|
||||
EShLangMiss,
|
||||
EShLangMissNV = EShLangMiss,
|
||||
EShLangCallable,
|
||||
EShLangCallableNV = EShLangCallable,
|
||||
EShLangTaskNV,
|
||||
EShLangMeshNV,
|
||||
LAST_ELEMENT_MARKER(EShLangCount),
|
||||
} EShLanguage; // would be better as stage, but this is ancient now
|
||||
|
||||
typedef enum : unsigned {
|
||||
EShLangVertexMask = (1 << EShLangVertex),
|
||||
EShLangTessControlMask = (1 << EShLangTessControl),
|
||||
EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
|
||||
EShLangGeometryMask = (1 << EShLangGeometry),
|
||||
EShLangFragmentMask = (1 << EShLangFragment),
|
||||
EShLangComputeMask = (1 << EShLangCompute),
|
||||
EShLangRayGenMask = (1 << EShLangRayGen),
|
||||
EShLangRayGenNVMask = EShLangRayGenMask,
|
||||
EShLangIntersectMask = (1 << EShLangIntersect),
|
||||
EShLangIntersectNVMask = EShLangIntersectMask,
|
||||
EShLangAnyHitMask = (1 << EShLangAnyHit),
|
||||
EShLangAnyHitNVMask = EShLangAnyHitMask,
|
||||
EShLangClosestHitMask = (1 << EShLangClosestHit),
|
||||
EShLangClosestHitNVMask = EShLangClosestHitMask,
|
||||
EShLangMissMask = (1 << EShLangMiss),
|
||||
EShLangMissNVMask = EShLangMissMask,
|
||||
EShLangCallableMask = (1 << EShLangCallable),
|
||||
EShLangCallableNVMask = EShLangCallableMask,
|
||||
EShLangTaskNVMask = (1 << EShLangTaskNV),
|
||||
EShLangMeshNVMask = (1 << EShLangMeshNV),
|
||||
LAST_ELEMENT_MARKER(EShLanguageMaskCount),
|
||||
} EShLanguageMask;
|
||||
|
||||
namespace glslang {
|
||||
|
||||
class TType;
|
||||
|
||||
typedef enum {
|
||||
EShSourceNone,
|
||||
EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL)
|
||||
EShSourceHlsl, // HLSL
|
||||
LAST_ELEMENT_MARKER(EShSourceCount),
|
||||
} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead
|
||||
|
||||
typedef enum {
|
||||
EShClientNone, // use when there is no client, e.g. for validation
|
||||
EShClientVulkan,
|
||||
EShClientOpenGL,
|
||||
LAST_ELEMENT_MARKER(EShClientCount),
|
||||
} EShClient;
|
||||
|
||||
typedef enum {
|
||||
EShTargetNone,
|
||||
EShTargetSpv, // SPIR-V (preferred spelling)
|
||||
EshTargetSpv = EShTargetSpv, // legacy spelling
|
||||
LAST_ELEMENT_MARKER(EShTargetCount),
|
||||
} EShTargetLanguage;
|
||||
|
||||
typedef enum {
|
||||
EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0
|
||||
EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
|
||||
EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
|
||||
EShTargetOpenGL_450 = 450, // OpenGL
|
||||
LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 4),
|
||||
} EShTargetClientVersion;
|
||||
|
||||
typedef EShTargetClientVersion EshTargetClientVersion;
|
||||
|
||||
typedef enum {
|
||||
EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0
|
||||
EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1
|
||||
EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2
|
||||
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
|
||||
EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
|
||||
EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
|
||||
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 6),
|
||||
} EShTargetLanguageVersion;
|
||||
|
||||
struct TInputLanguage {
|
||||
EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone
|
||||
EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone
|
||||
EShClient dialect;
|
||||
int dialectVersion; // version of client's language definition, not the client (when not EShClientNone)
|
||||
bool vulkanRulesRelaxed;
|
||||
};
|
||||
|
||||
struct TClient {
|
||||
EShClient client;
|
||||
EShTargetClientVersion version; // version of client itself (not the client's input dialect)
|
||||
};
|
||||
|
||||
struct TTarget {
|
||||
EShTargetLanguage language;
|
||||
EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header
|
||||
bool hlslFunctionality1; // can target hlsl_functionality1 extension(s)
|
||||
};
|
||||
|
||||
// All source/client/target versions and settings.
|
||||
// Can override previous methods of setting, when items are set here.
|
||||
// Expected to grow, as more are added, rather than growing parameter lists.
|
||||
struct TEnvironment {
|
||||
TInputLanguage input; // definition of the input language
|
||||
TClient client; // what client is the overall compilation being done for?
|
||||
TTarget target; // what to generate
|
||||
};
|
||||
|
||||
GLSLANG_EXPORT const char* StageName(EShLanguage);
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
//
|
||||
// Types of output the linker will create.
|
||||
//
|
||||
typedef enum {
|
||||
EShExVertexFragment,
|
||||
EShExFragment
|
||||
} EShExecutable;
|
||||
|
||||
//
|
||||
// Optimization level for the compiler.
|
||||
//
|
||||
typedef enum {
|
||||
EShOptNoGeneration,
|
||||
EShOptNone,
|
||||
EShOptSimple, // Optimizations that can be done quickly
|
||||
EShOptFull, // Optimizations that will take more time
|
||||
LAST_ELEMENT_MARKER(EshOptLevelCount),
|
||||
} EShOptimizationLevel;
|
||||
|
||||
//
|
||||
// Texture and Sampler transformation mode.
|
||||
//
|
||||
typedef enum {
|
||||
EShTexSampTransKeep, // keep textures and samplers as is (default)
|
||||
EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers
|
||||
LAST_ELEMENT_MARKER(EShTexSampTransCount),
|
||||
} EShTextureSamplerTransformMode;
|
||||
|
||||
//
|
||||
// Message choices for what errors and warnings are given.
|
||||
//
|
||||
enum EShMessages : unsigned {
|
||||
EShMsgDefault = 0, // default is to give all required errors and extra warnings
|
||||
EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input
|
||||
EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification
|
||||
EShMsgAST = (1 << 2), // print the AST intermediate representation
|
||||
EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation
|
||||
EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V
|
||||
EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor
|
||||
EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
|
||||
EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit
|
||||
EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions
|
||||
EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules
|
||||
EShMsgDebugInfo = (1 << 10), // save debug information
|
||||
EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
|
||||
EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
|
||||
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics)
|
||||
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
|
||||
LAST_ELEMENT_MARKER(EShMsgCount),
|
||||
};
|
||||
|
||||
//
|
||||
// Options for building reflection
|
||||
//
|
||||
typedef enum {
|
||||
EShReflectionDefault = 0, // default is original behaviour before options were added
|
||||
EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
|
||||
EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
|
||||
EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
|
||||
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
|
||||
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
|
||||
EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
|
||||
EShReflectionAllIOVariables = (1 << 6), // reflect all input/output variables, even if they are inactive
|
||||
EShReflectionSharedStd140SSBO = (1 << 7), // Apply std140/shared rules for ubo to ssbo
|
||||
EShReflectionSharedStd140UBO = (1 << 8), // Apply std140/shared rules for ubo to ssbo
|
||||
LAST_ELEMENT_MARKER(EShReflectionCount),
|
||||
} EShReflectionOptions;
|
||||
|
||||
//
|
||||
// Build a table for bindings. This can be used for locating
|
||||
// attributes, uniforms, globals, etc., as needed.
|
||||
//
|
||||
typedef struct {
|
||||
const char* name;
|
||||
int binding;
|
||||
} ShBinding;
|
||||
|
||||
typedef struct {
|
||||
int numBindings;
|
||||
ShBinding* bindings; // array of bindings
|
||||
} ShBindingTable;
|
||||
|
||||
//
|
||||
// ShHandle held by but opaque to the driver. It is allocated,
|
||||
// managed, and de-allocated by the compiler/linker. It's contents
|
||||
// are defined by and used by the compiler and linker. For example,
|
||||
// symbol table information and object code passed from the compiler
|
||||
// to the linker can be stored where ShHandle points.
|
||||
//
|
||||
// If handle creation fails, 0 will be returned.
|
||||
//
|
||||
typedef void* ShHandle;
|
||||
|
||||
//
|
||||
// Driver calls these to create and destroy compiler/linker
|
||||
// objects.
|
||||
//
|
||||
GLSLANG_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader
|
||||
GLSLANG_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair
|
||||
GLSLANG_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object)
|
||||
GLSLANG_EXPORT void ShDestruct(ShHandle);
|
||||
|
||||
//
|
||||
// The return value of ShCompile is boolean, non-zero indicating
|
||||
// success.
|
||||
//
|
||||
// The info-log should be written by ShCompile into
|
||||
// ShHandle, so it can answer future queries.
|
||||
//
|
||||
GLSLANG_EXPORT int ShCompile(
|
||||
const ShHandle,
|
||||
const char* const shaderStrings[],
|
||||
const int numStrings,
|
||||
const int* lengths,
|
||||
const EShOptimizationLevel,
|
||||
const TBuiltInResource *resources,
|
||||
int debugOptions,
|
||||
int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader
|
||||
bool forwardCompatible = false, // give errors for use of deprecated features
|
||||
EShMessages messages = EShMsgDefault // warnings and errors
|
||||
);
|
||||
|
||||
GLSLANG_EXPORT int ShLinkExt(
|
||||
const ShHandle, // linker object
|
||||
const ShHandle h[], // compiler objects to link together
|
||||
const int numHandles);
|
||||
|
||||
//
|
||||
// ShSetEncrpytionMethod is a place-holder for specifying
|
||||
// how source code is encrypted.
|
||||
//
|
||||
GLSLANG_EXPORT void ShSetEncryptionMethod(ShHandle);
|
||||
|
||||
//
|
||||
// All the following return 0 if the information is not
|
||||
// available in the object passed down, or the object is bad.
|
||||
//
|
||||
GLSLANG_EXPORT const char* ShGetInfoLog(const ShHandle);
|
||||
GLSLANG_EXPORT const void* ShGetExecutable(const ShHandle);
|
||||
GLSLANG_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing
|
||||
GLSLANG_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings
|
||||
//
|
||||
// Tell the linker to never assign a vertex attribute to this list of physical attributes
|
||||
//
|
||||
GLSLANG_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
|
||||
|
||||
//
|
||||
// Returns the location ID of the named uniform.
|
||||
// Returns -1 if error.
|
||||
//
|
||||
GLSLANG_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end extern "C"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Deferred-Lowering C++ Interface
|
||||
// -----------------------------------
|
||||
//
|
||||
// Below is a new alternate C++ interface, which deprecates the above
|
||||
// opaque handle-based interface.
|
||||
//
|
||||
// The below is further designed to handle multiple compilation units per stage, where
|
||||
// the intermediate results, including the parse tree, are preserved until link time,
|
||||
// rather than the above interface which is designed to have each compilation unit
|
||||
// lowered at compile time. In the above model, linking occurs on the lowered results,
|
||||
// whereas in this model intra-stage linking can occur at the parse tree
|
||||
// (treeRoot in TIntermediate) level, and then a full stage can be lowered.
|
||||
//
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
class TCompiler;
|
||||
class TInfoSink;
|
||||
|
||||
namespace glslang {
|
||||
|
||||
struct Version {
|
||||
int major;
|
||||
int minor;
|
||||
int patch;
|
||||
const char* flavor;
|
||||
};
|
||||
|
||||
GLSLANG_EXPORT Version GetVersion();
|
||||
GLSLANG_EXPORT const char* GetEsslVersionString();
|
||||
GLSLANG_EXPORT const char* GetGlslVersionString();
|
||||
GLSLANG_EXPORT int GetKhronosToolId();
|
||||
|
||||
class TIntermediate;
|
||||
class TProgram;
|
||||
class TPoolAllocator;
|
||||
|
||||
// Call this exactly once per process before using anything else
|
||||
GLSLANG_EXPORT bool InitializeProcess();
|
||||
|
||||
// Call once per process to tear down everything
|
||||
GLSLANG_EXPORT void FinalizeProcess();
|
||||
|
||||
// Resource type for IO resolver
|
||||
enum TResourceType {
|
||||
EResSampler,
|
||||
EResTexture,
|
||||
EResImage,
|
||||
EResUbo,
|
||||
EResSsbo,
|
||||
EResUav,
|
||||
EResCount
|
||||
};
|
||||
|
||||
enum TBlockStorageClass
|
||||
{
|
||||
EbsUniform = 0,
|
||||
EbsStorageBuffer,
|
||||
EbsPushConstant,
|
||||
EbsNone, // not a uniform or buffer variable
|
||||
EbsCount,
|
||||
};
|
||||
|
||||
// Make one TShader per shader that you will link into a program. Then
|
||||
// - provide the shader through setStrings() or setStringsWithLengths()
|
||||
// - optionally call setEnv*(), see below for more detail
|
||||
// - optionally use setPreamble() to set a special shader string that will be
|
||||
// processed before all others but won't affect the validity of #version
|
||||
// - optionally call addProcesses() for each setting/transform,
|
||||
// see comment for class TProcesses
|
||||
// - call parse(): source language and target environment must be selected
|
||||
// either by correct setting of EShMessages sent to parse(), or by
|
||||
// explicitly calling setEnv*()
|
||||
// - query the info logs
|
||||
//
|
||||
// N.B.: Does not yet support having the same TShader instance being linked into
|
||||
// multiple programs.
|
||||
//
|
||||
// N.B.: Destruct a linked program *before* destructing the shaders linked into it.
|
||||
//
|
||||
class TShader {
|
||||
public:
|
||||
GLSLANG_EXPORT explicit TShader(EShLanguage);
|
||||
GLSLANG_EXPORT virtual ~TShader();
|
||||
GLSLANG_EXPORT void setStrings(const char* const* s, int n);
|
||||
GLSLANG_EXPORT void setStringsWithLengths(
|
||||
const char* const* s, const int* l, int n);
|
||||
GLSLANG_EXPORT void setStringsWithLengthsAndNames(
|
||||
const char* const* s, const int* l, const char* const* names, int n);
|
||||
void setPreamble(const char* s) { preamble = s; }
|
||||
GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
|
||||
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
|
||||
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
|
||||
GLSLANG_EXPORT void setUniqueId(unsigned long long id);
|
||||
|
||||
// IO resolver binding data: see comments in ShaderLang.cpp
|
||||
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
|
||||
GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
|
||||
GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
|
||||
GLSLANG_EXPORT void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
|
||||
GLSLANG_EXPORT void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
|
||||
GLSLANG_EXPORT void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
|
||||
GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
|
||||
GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
|
||||
GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
|
||||
GLSLANG_EXPORT void setResourceSetBinding(const std::vector<std::string>& base);
|
||||
GLSLANG_EXPORT void setAutoMapBindings(bool map);
|
||||
GLSLANG_EXPORT void setAutoMapLocations(bool map);
|
||||
GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
|
||||
GLSLANG_EXPORT void setUniformLocationBase(int base);
|
||||
GLSLANG_EXPORT void setInvertY(bool invert);
|
||||
#ifdef ENABLE_HLSL
|
||||
GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
|
||||
GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);
|
||||
#endif
|
||||
GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
|
||||
GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
|
||||
GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
|
||||
GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
|
||||
|
||||
GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name);
|
||||
GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name);
|
||||
GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set);
|
||||
GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding);
|
||||
GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
|
||||
GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
|
||||
|
||||
// For setting up the environment (cleared to nothingness in the constructor).
|
||||
// These must be called so that parsing is done for the right source language and
|
||||
// target environment, either indirectly through TranslateEnvironment() based on
|
||||
// EShMessages et. al., or directly by the user.
|
||||
//
|
||||
// setEnvInput: The input source language and stage. If generating code for a
|
||||
// specific client, the input client semantics to use and the
|
||||
// version of that client's input semantics to use, otherwise
|
||||
// use EShClientNone and version of 0, e.g. for validation mode.
|
||||
// Note 'version' does not describe the target environment,
|
||||
// just the version of the source dialect to compile under.
|
||||
//
|
||||
// See the definitions of TEnvironment, EShSource, EShLanguage,
|
||||
// and EShClient for choices and more detail.
|
||||
//
|
||||
// setEnvClient: The client that will be hosting the execution, and it's version.
|
||||
// Note 'version' is not the version of the languages involved, but
|
||||
// the version of the client environment.
|
||||
// Use EShClientNone and version of 0 if there is no client, e.g.
|
||||
// for validation mode.
|
||||
//
|
||||
// See EShTargetClientVersion for choices.
|
||||
//
|
||||
// setEnvTarget: The language to translate to when generating code, and that
|
||||
// language's version.
|
||||
// Use EShTargetNone and version of 0 if there is no client, e.g.
|
||||
// for validation mode.
|
||||
//
|
||||
void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version)
|
||||
{
|
||||
environment.input.languageFamily = lang;
|
||||
environment.input.stage = envStage;
|
||||
environment.input.dialect = client;
|
||||
environment.input.dialectVersion = version;
|
||||
}
|
||||
void setEnvClient(EShClient client, EShTargetClientVersion version)
|
||||
{
|
||||
environment.client.client = client;
|
||||
environment.client.version = version;
|
||||
}
|
||||
void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version)
|
||||
{
|
||||
environment.target.language = lang;
|
||||
environment.target.version = version;
|
||||
}
|
||||
|
||||
void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; }
|
||||
|
||||
#ifdef ENABLE_HLSL
|
||||
void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; }
|
||||
bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; }
|
||||
#else
|
||||
bool getEnvTargetHlslFunctionality1() const { return false; }
|
||||
#endif
|
||||
|
||||
void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; }
|
||||
bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; }
|
||||
|
||||
// Interface to #include handlers.
|
||||
//
|
||||
// To support #include, a client of Glslang does the following:
|
||||
// 1. Call setStringsWithNames to set the source strings and associated
|
||||
// names. For example, the names could be the names of the files
|
||||
// containing the shader sources.
|
||||
// 2. Call parse with an Includer.
|
||||
//
|
||||
// When the Glslang parser encounters an #include directive, it calls
|
||||
// the Includer's include method with the requested include name
|
||||
// together with the current string name. The returned IncludeResult
|
||||
// contains the fully resolved name of the included source, together
|
||||
// with the source text that should replace the #include directive
|
||||
// in the source stream. After parsing that source, Glslang will
|
||||
// release the IncludeResult object.
|
||||
class Includer {
|
||||
public:
|
||||
// An IncludeResult contains the resolved name and content of a source
|
||||
// inclusion.
|
||||
struct IncludeResult {
|
||||
IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) :
|
||||
headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { }
|
||||
// For a successful inclusion, the fully resolved name of the requested
|
||||
// include. For example, in a file system-based includer, full resolution
|
||||
// should convert a relative path name into an absolute path name.
|
||||
// For a failed inclusion, this is an empty string.
|
||||
const std::string headerName;
|
||||
// The content and byte length of the requested inclusion. The
|
||||
// Includer producing this IncludeResult retains ownership of the
|
||||
// storage.
|
||||
// For a failed inclusion, the header
|
||||
// field points to a string containing error details.
|
||||
const char* const headerData;
|
||||
const size_t headerLength;
|
||||
// Include resolver's context.
|
||||
void* userData;
|
||||
protected:
|
||||
IncludeResult& operator=(const IncludeResult&);
|
||||
IncludeResult();
|
||||
};
|
||||
|
||||
// For both include methods below:
|
||||
//
|
||||
// Resolves an inclusion request by name, current source name,
|
||||
// and include depth.
|
||||
// On success, returns an IncludeResult containing the resolved name
|
||||
// and content of the include.
|
||||
// On failure, returns a nullptr, or an IncludeResult
|
||||
// with an empty string for the headerName and error details in the
|
||||
// header field.
|
||||
// The Includer retains ownership of the contents
|
||||
// of the returned IncludeResult value, and those contents must
|
||||
// remain valid until the releaseInclude method is called on that
|
||||
// IncludeResult object.
|
||||
//
|
||||
// Note "local" vs. "system" is not an "either/or": "local" is an
|
||||
// extra thing to do over "system". Both might get called, as per
|
||||
// the C++ specification.
|
||||
|
||||
// For the "system" or <>-style includes; search the "system" paths.
|
||||
virtual IncludeResult* includeSystem(const char* /*headerName*/,
|
||||
const char* /*includerName*/,
|
||||
size_t /*inclusionDepth*/) { return nullptr; }
|
||||
|
||||
// For the "local"-only aspect of a "" include. Should not search in the
|
||||
// "system" paths, because on returning a failure, the parser will
|
||||
// call includeSystem() to look in the "system" locations.
|
||||
virtual IncludeResult* includeLocal(const char* /*headerName*/,
|
||||
const char* /*includerName*/,
|
||||
size_t /*inclusionDepth*/) { return nullptr; }
|
||||
|
||||
// Signals that the parser will no longer use the contents of the
|
||||
// specified IncludeResult.
|
||||
virtual void releaseInclude(IncludeResult*) = 0;
|
||||
virtual ~Includer() {}
|
||||
};
|
||||
|
||||
// Fail all Includer searches
|
||||
class ForbidIncluder : public Includer {
|
||||
public:
|
||||
virtual void releaseInclude(IncludeResult*) override { }
|
||||
};
|
||||
|
||||
GLSLANG_EXPORT bool parse(
|
||||
const TBuiltInResource*, int defaultVersion, EProfile defaultProfile,
|
||||
bool forceDefaultVersionAndProfile, bool forwardCompatible,
|
||||
EShMessages, Includer&);
|
||||
|
||||
bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
|
||||
bool forwardCompatible, EShMessages messages)
|
||||
{
|
||||
TShader::ForbidIncluder includer;
|
||||
return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer);
|
||||
}
|
||||
|
||||
// Equivalent to parse() without a default profile and without forcing defaults.
|
||||
bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
|
||||
{
|
||||
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
|
||||
}
|
||||
|
||||
bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages,
|
||||
Includer& includer)
|
||||
{
|
||||
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
|
||||
}
|
||||
|
||||
// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
|
||||
// is not an officially supported or fully working path.
|
||||
GLSLANG_EXPORT bool preprocess(
|
||||
const TBuiltInResource* builtInResources, int defaultVersion,
|
||||
EProfile defaultProfile, bool forceDefaultVersionAndProfile,
|
||||
bool forwardCompatible, EShMessages message, std::string* outputString,
|
||||
Includer& includer);
|
||||
|
||||
GLSLANG_EXPORT const char* getInfoLog();
|
||||
GLSLANG_EXPORT const char* getInfoDebugLog();
|
||||
EShLanguage getStage() const { return stage; }
|
||||
TIntermediate* getIntermediate() const { return intermediate; }
|
||||
|
||||
protected:
|
||||
TPoolAllocator* pool;
|
||||
EShLanguage stage;
|
||||
TCompiler* compiler;
|
||||
TIntermediate* intermediate;
|
||||
TInfoSink* infoSink;
|
||||
// strings and lengths follow the standard for glShaderSource:
|
||||
// strings is an array of numStrings pointers to string data.
|
||||
// lengths can be null, but if not it is an array of numStrings
|
||||
// integers containing the length of the associated strings.
|
||||
// if lengths is null or lengths[n] < 0 the associated strings[n] is
|
||||
// assumed to be null-terminated.
|
||||
// stringNames is the optional names for all the strings. If stringNames
|
||||
// is null, then none of the strings has name. If a certain element in
|
||||
// stringNames is null, then the corresponding string does not have name.
|
||||
const char* const* strings; // explicit code to compile, see previous comment
|
||||
const int* lengths;
|
||||
const char* const* stringNames;
|
||||
int numStrings; // size of the above arrays
|
||||
const char* preamble; // string of implicit code to compile before the explicitly provided code
|
||||
|
||||
// a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
|
||||
std::string sourceEntryPointName;
|
||||
|
||||
TEnvironment environment;
|
||||
|
||||
friend class TProgram;
|
||||
|
||||
private:
|
||||
TShader& operator=(TShader&);
|
||||
};
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
|
||||
//
|
||||
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
|
||||
//
|
||||
|
||||
// Data needed for just a single object at the granularity exchanged by the reflection API
|
||||
class TObjectReflection {
|
||||
public:
|
||||
GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
|
||||
|
||||
GLSLANG_EXPORT const TType* getType() const { return type; }
|
||||
GLSLANG_EXPORT int getBinding() const;
|
||||
GLSLANG_EXPORT void dump() const;
|
||||
static TObjectReflection badReflection() { return TObjectReflection(); }
|
||||
|
||||
std::string name;
|
||||
int offset;
|
||||
int glDefineType;
|
||||
int size; // data size in bytes for a block, array size for a (non-block) object that's an array
|
||||
int index;
|
||||
int counterIndex;
|
||||
int numMembers;
|
||||
int arrayStride; // stride of an array variable
|
||||
int topLevelArraySize; // size of the top-level variable in a storage buffer member
|
||||
int topLevelArrayStride; // stride of the top-level variable in a storage buffer member
|
||||
EShLanguageMask stages;
|
||||
|
||||
protected:
|
||||
TObjectReflection()
|
||||
: offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0),
|
||||
topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
const TType* type;
|
||||
};
|
||||
|
||||
class TReflection;
|
||||
class TIoMapper;
|
||||
struct TVarEntryInfo;
|
||||
|
||||
// Allows to customize the binding layout after linking.
|
||||
// All used uniform variables will invoke at least validateBinding.
|
||||
// If validateBinding returned true then the other resolveBinding,
|
||||
// resolveSet, and resolveLocation are invoked to resolve the binding
|
||||
// and descriptor set index respectively.
|
||||
//
|
||||
// Invocations happen in a particular order:
|
||||
// 1) all shader inputs
|
||||
// 2) all shader outputs
|
||||
// 3) all uniforms with binding and set already defined
|
||||
// 4) all uniforms with binding but no set defined
|
||||
// 5) all uniforms with set but no binding defined
|
||||
// 6) all uniforms with no binding and no set defined
|
||||
//
|
||||
// mapIO will use this resolver in two phases. The first
|
||||
// phase is a notification phase, calling the corresponging
|
||||
// notifiy callbacks, this phase ends with a call to endNotifications.
|
||||
// Phase two starts directly after the call to endNotifications
|
||||
// and calls all other callbacks to validate and to get the
|
||||
// bindings, sets, locations, component and color indices.
|
||||
//
|
||||
// NOTE: that still limit checks are applied to bindings and sets
|
||||
// and may result in an error.
|
||||
class TIoMapResolver
|
||||
{
|
||||
public:
|
||||
virtual ~TIoMapResolver() {}
|
||||
|
||||
// Should return true if the resulting/current binding would be okay.
|
||||
// Basic idea is to do aliasing binding checks with this.
|
||||
virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return a value >= 0 if the current binding should be overridden.
|
||||
// Return -1 if the current binding (including no binding) should be kept.
|
||||
virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return a value >= 0 if the current set should be overridden.
|
||||
// Return -1 if the current set (including no set) should be kept.
|
||||
virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return a value >= 0 if the current location should be overridden.
|
||||
// Return -1 if the current location (including no location) should be kept.
|
||||
virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return true if the resulting/current setup would be okay.
|
||||
// Basic idea is to do aliasing checks and reject invalid semantic names.
|
||||
virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return a value >= 0 if the current location should be overridden.
|
||||
// Return -1 if the current location (including no location) should be kept.
|
||||
virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return a value >= 0 if the current component index should be overridden.
|
||||
// Return -1 if the current component index (including no index) should be kept.
|
||||
virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Should return a value >= 0 if the current color index should be overridden.
|
||||
// Return -1 if the current color index (including no index) should be kept.
|
||||
virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Notification of a uniform variable
|
||||
virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Notification of a in or out variable
|
||||
virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0;
|
||||
// Called by mapIO when it starts its notify pass for the given stage
|
||||
virtual void beginNotifications(EShLanguage stage) = 0;
|
||||
// Called by mapIO when it has finished the notify pass
|
||||
virtual void endNotifications(EShLanguage stage) = 0;
|
||||
// Called by mipIO when it starts its resolve pass for the given stage
|
||||
virtual void beginResolve(EShLanguage stage) = 0;
|
||||
// Called by mapIO when it has finished the resolve pass
|
||||
virtual void endResolve(EShLanguage stage) = 0;
|
||||
// Called by mapIO when it starts its symbol collect for teh given stage
|
||||
virtual void beginCollect(EShLanguage stage) = 0;
|
||||
// Called by mapIO when it has finished the symbol collect
|
||||
virtual void endCollect(EShLanguage stage) = 0;
|
||||
// Called by TSlotCollector to resolve storage locations or bindings
|
||||
virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
|
||||
// Called by TSlotCollector to resolve resource locations or bindings
|
||||
virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
|
||||
// Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
|
||||
virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0;
|
||||
};
|
||||
|
||||
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
|
||||
|
||||
// Make one TProgram per set of shaders that will get linked together. Add all
|
||||
// the shaders that are to be linked together. After calling shader.parse()
|
||||
// for all shaders, call link().
|
||||
//
|
||||
// N.B.: Destruct a linked program *before* destructing the shaders linked into it.
|
||||
//
|
||||
class TProgram {
|
||||
public:
|
||||
GLSLANG_EXPORT TProgram();
|
||||
GLSLANG_EXPORT virtual ~TProgram();
|
||||
void addShader(TShader* shader) { stages[shader->stage].push_back(shader); }
|
||||
std::list<TShader*>& getShaders(EShLanguage stage) { return stages[stage]; }
|
||||
// Link Validation interface
|
||||
GLSLANG_EXPORT bool link(EShMessages);
|
||||
GLSLANG_EXPORT const char* getInfoLog();
|
||||
GLSLANG_EXPORT const char* getInfoDebugLog();
|
||||
|
||||
TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; }
|
||||
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
|
||||
// Reflection Interface
|
||||
|
||||
// call first, to do liveness analysis, index mapping, etc.; returns false on failure
|
||||
GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault);
|
||||
GLSLANG_EXPORT unsigned getLocalSize(int dim) const; // return dim'th local size
|
||||
GLSLANG_EXPORT int getReflectionIndex(const char *name) const;
|
||||
GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
|
||||
GLSLANG_EXPORT int getNumUniformVariables() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const;
|
||||
GLSLANG_EXPORT int getNumUniformBlocks() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const;
|
||||
GLSLANG_EXPORT int getNumPipeInputs() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const;
|
||||
GLSLANG_EXPORT int getNumPipeOutputs() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const;
|
||||
GLSLANG_EXPORT int getNumBufferVariables() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const;
|
||||
GLSLANG_EXPORT int getNumBufferBlocks() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const;
|
||||
GLSLANG_EXPORT int getNumAtomicCounters() const;
|
||||
GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const;
|
||||
|
||||
// Legacy Reflection Interface - expressed in terms of above interface
|
||||
|
||||
// can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS)
|
||||
int getNumLiveUniformVariables() const { return getNumUniformVariables(); }
|
||||
|
||||
// can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS)
|
||||
int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); }
|
||||
|
||||
// can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES)
|
||||
int getNumLiveAttributes() const { return getNumPipeInputs(); }
|
||||
|
||||
// can be used for glGetUniformIndices()
|
||||
int getUniformIndex(const char *name) const { return getReflectionIndex(name); }
|
||||
|
||||
int getPipeIOIndex(const char *name, const bool inOrOut) const
|
||||
{ return getReflectionPipeIOIndex(name, inOrOut); }
|
||||
|
||||
// can be used for "name" part of glGetActiveUniform()
|
||||
const char *getUniformName(int index) const { return getUniform(index).name.c_str(); }
|
||||
|
||||
// returns the binding number
|
||||
int getUniformBinding(int index) const { return getUniform(index).getBinding(); }
|
||||
|
||||
// returns Shaders Stages where a Uniform is present
|
||||
EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; }
|
||||
|
||||
// can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
|
||||
int getUniformBlockIndex(int index) const { return getUniform(index).index; }
|
||||
|
||||
// can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
|
||||
int getUniformType(int index) const { return getUniform(index).glDefineType; }
|
||||
|
||||
// can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
|
||||
int getUniformBufferOffset(int index) const { return getUniform(index).offset; }
|
||||
|
||||
// can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
|
||||
int getUniformArraySize(int index) const { return getUniform(index).size; }
|
||||
|
||||
// returns a TType*
|
||||
const TType *getUniformTType(int index) const { return getUniform(index).getType(); }
|
||||
|
||||
// can be used for glGetActiveUniformBlockName()
|
||||
const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); }
|
||||
|
||||
// can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
|
||||
int getUniformBlockSize(int index) const { return getUniformBlock(index).size; }
|
||||
|
||||
// returns the block binding number
|
||||
int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); }
|
||||
|
||||
// returns block index of associated counter.
|
||||
int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; }
|
||||
|
||||
// returns a TType*
|
||||
const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); }
|
||||
|
||||
// can be used for glGetActiveAttrib()
|
||||
const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); }
|
||||
|
||||
// can be used for glGetActiveAttrib()
|
||||
int getAttributeType(int index) const { return getPipeInput(index).glDefineType; }
|
||||
|
||||
// returns a TType*
|
||||
const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); }
|
||||
|
||||
GLSLANG_EXPORT void dumpReflection();
|
||||
// I/O mapping: apply base offsets and map live unbound variables
|
||||
// If resolver is not provided it uses the previous approach
|
||||
// and respects auto assignment and offsets.
|
||||
GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
|
||||
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
|
||||
|
||||
protected:
|
||||
GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
|
||||
GLSLANG_EXPORT bool crossStageCheck(EShMessages);
|
||||
|
||||
TPoolAllocator* pool;
|
||||
std::list<TShader*> stages[EShLangCount];
|
||||
TIntermediate* intermediate[EShLangCount];
|
||||
bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage
|
||||
TInfoSink* infoSink;
|
||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||
TReflection* reflection;
|
||||
#endif
|
||||
bool linked;
|
||||
|
||||
private:
|
||||
TProgram(TProgram&);
|
||||
TProgram& operator=(TProgram&);
|
||||
};
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _COMPILER_INTERFACE_INCLUDED_
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLextAMD_H
|
||||
#define GLSLextAMD_H
|
||||
|
||||
static const int GLSLextAMDVersion = 100;
|
||||
static const int GLSLextAMDRevision = 7;
|
||||
|
||||
// SPV_AMD_shader_ballot
|
||||
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
|
||||
|
||||
enum ShaderBallotAMD {
|
||||
ShaderBallotBadAMD = 0, // Don't use
|
||||
|
||||
SwizzleInvocationsAMD = 1,
|
||||
SwizzleInvocationsMaskedAMD = 2,
|
||||
WriteInvocationAMD = 3,
|
||||
MbcntAMD = 4,
|
||||
|
||||
ShaderBallotCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_shader_trinary_minmax
|
||||
static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax";
|
||||
|
||||
enum ShaderTrinaryMinMaxAMD {
|
||||
ShaderTrinaryMinMaxBadAMD = 0, // Don't use
|
||||
|
||||
FMin3AMD = 1,
|
||||
UMin3AMD = 2,
|
||||
SMin3AMD = 3,
|
||||
FMax3AMD = 4,
|
||||
UMax3AMD = 5,
|
||||
SMax3AMD = 6,
|
||||
FMid3AMD = 7,
|
||||
UMid3AMD = 8,
|
||||
SMid3AMD = 9,
|
||||
|
||||
ShaderTrinaryMinMaxCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_shader_explicit_vertex_parameter
|
||||
static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
|
||||
|
||||
enum ShaderExplicitVertexParameterAMD {
|
||||
ShaderExplicitVertexParameterBadAMD = 0, // Don't use
|
||||
|
||||
InterpolateAtVertexAMD = 1,
|
||||
|
||||
ShaderExplicitVertexParameterCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_gcn_shader
|
||||
static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader";
|
||||
|
||||
enum GcnShaderAMD {
|
||||
GcnShaderBadAMD = 0, // Don't use
|
||||
|
||||
CubeFaceIndexAMD = 1,
|
||||
CubeFaceCoordAMD = 2,
|
||||
TimeAMD = 3,
|
||||
|
||||
GcnShaderCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_gpu_shader_half_float
|
||||
static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float";
|
||||
|
||||
// SPV_AMD_texture_gather_bias_lod
|
||||
static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod";
|
||||
|
||||
// SPV_AMD_gpu_shader_int16
|
||||
static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16";
|
||||
|
||||
// SPV_AMD_shader_image_load_store_lod
|
||||
static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod";
|
||||
|
||||
// SPV_AMD_shader_fragment_mask
|
||||
static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask";
|
||||
|
||||
// SPV_AMD_gpu_shader_half_float_fetch
|
||||
static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch";
|
||||
|
||||
#endif // #ifndef GLSLextAMD_H
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLextEXT_H
|
||||
#define GLSLextEXT_H
|
||||
|
||||
static const int GLSLextEXTVersion = 100;
|
||||
static const int GLSLextEXTRevision = 2;
|
||||
|
||||
static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export";
|
||||
static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer";
|
||||
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
|
||||
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
|
||||
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
|
||||
static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
|
||||
static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
|
||||
|
||||
#endif // #ifndef GLSLextEXT_H
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
** Copyright (c) 2014-2020 The Khronos Group Inc.
|
||||
** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLextKHR_H
|
||||
#define GLSLextKHR_H
|
||||
|
||||
static const int GLSLextKHRVersion = 100;
|
||||
static const int GLSLextKHRRevision = 2;
|
||||
|
||||
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
|
||||
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
|
||||
static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group";
|
||||
static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview";
|
||||
static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters";
|
||||
static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage";
|
||||
static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage";
|
||||
static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
|
||||
static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
|
||||
static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model";
|
||||
static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer";
|
||||
static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer";
|
||||
static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
|
||||
static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock";
|
||||
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
|
||||
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
|
||||
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
|
||||
static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate";
|
||||
static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation";
|
||||
static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
|
||||
|
||||
#endif // #ifndef GLSLextKHR_H
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
** Copyright (c) 2014-2017 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLextNV_H
|
||||
#define GLSLextNV_H
|
||||
|
||||
enum BuiltIn;
|
||||
enum Decoration;
|
||||
enum Op;
|
||||
enum Capability;
|
||||
|
||||
static const int GLSLextNVVersion = 100;
|
||||
static const int GLSLextNVRevision = 11;
|
||||
|
||||
//SPV_NV_sample_mask_override_coverage
|
||||
const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
|
||||
|
||||
//SPV_NV_geometry_shader_passthrough
|
||||
const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough";
|
||||
|
||||
//SPV_NV_viewport_array2
|
||||
const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2";
|
||||
const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array";
|
||||
|
||||
//SPV_NV_stereo_view_rendering
|
||||
const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering";
|
||||
|
||||
//SPV_NVX_multiview_per_view_attributes
|
||||
const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes";
|
||||
|
||||
//SPV_NV_shader_subgroup_partitioned
|
||||
const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned";
|
||||
|
||||
//SPV_NV_fragment_shader_barycentric
|
||||
const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric";
|
||||
|
||||
//SPV_NV_compute_shader_derivatives
|
||||
const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives";
|
||||
|
||||
//SPV_NV_shader_image_footprint
|
||||
const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint";
|
||||
|
||||
//SPV_NV_mesh_shader
|
||||
const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader";
|
||||
|
||||
//SPV_NV_raytracing
|
||||
const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing";
|
||||
|
||||
//SPV_NV_shading_rate
|
||||
const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate";
|
||||
|
||||
//SPV_NV_cooperative_matrix
|
||||
const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix";
|
||||
|
||||
//SPV_NV_shader_sm_builtins
|
||||
const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins";
|
||||
|
||||
#endif // #ifndef GLSLextNV_H
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLstd450_H
|
||||
#define GLSLstd450_H
|
||||
|
||||
static const int GLSLstd450Version = 100;
|
||||
static const int GLSLstd450Revision = 1;
|
||||
|
||||
enum GLSLstd450 {
|
||||
GLSLstd450Bad = 0, // Don't use
|
||||
|
||||
GLSLstd450Round = 1,
|
||||
GLSLstd450RoundEven = 2,
|
||||
GLSLstd450Trunc = 3,
|
||||
GLSLstd450FAbs = 4,
|
||||
GLSLstd450SAbs = 5,
|
||||
GLSLstd450FSign = 6,
|
||||
GLSLstd450SSign = 7,
|
||||
GLSLstd450Floor = 8,
|
||||
GLSLstd450Ceil = 9,
|
||||
GLSLstd450Fract = 10,
|
||||
|
||||
GLSLstd450Radians = 11,
|
||||
GLSLstd450Degrees = 12,
|
||||
GLSLstd450Sin = 13,
|
||||
GLSLstd450Cos = 14,
|
||||
GLSLstd450Tan = 15,
|
||||
GLSLstd450Asin = 16,
|
||||
GLSLstd450Acos = 17,
|
||||
GLSLstd450Atan = 18,
|
||||
GLSLstd450Sinh = 19,
|
||||
GLSLstd450Cosh = 20,
|
||||
GLSLstd450Tanh = 21,
|
||||
GLSLstd450Asinh = 22,
|
||||
GLSLstd450Acosh = 23,
|
||||
GLSLstd450Atanh = 24,
|
||||
GLSLstd450Atan2 = 25,
|
||||
|
||||
GLSLstd450Pow = 26,
|
||||
GLSLstd450Exp = 27,
|
||||
GLSLstd450Log = 28,
|
||||
GLSLstd450Exp2 = 29,
|
||||
GLSLstd450Log2 = 30,
|
||||
GLSLstd450Sqrt = 31,
|
||||
GLSLstd450InverseSqrt = 32,
|
||||
|
||||
GLSLstd450Determinant = 33,
|
||||
GLSLstd450MatrixInverse = 34,
|
||||
|
||||
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
|
||||
GLSLstd450ModfStruct = 36, // no OpVariable operand
|
||||
GLSLstd450FMin = 37,
|
||||
GLSLstd450UMin = 38,
|
||||
GLSLstd450SMin = 39,
|
||||
GLSLstd450FMax = 40,
|
||||
GLSLstd450UMax = 41,
|
||||
GLSLstd450SMax = 42,
|
||||
GLSLstd450FClamp = 43,
|
||||
GLSLstd450UClamp = 44,
|
||||
GLSLstd450SClamp = 45,
|
||||
GLSLstd450FMix = 46,
|
||||
GLSLstd450IMix = 47, // Reserved
|
||||
GLSLstd450Step = 48,
|
||||
GLSLstd450SmoothStep = 49,
|
||||
|
||||
GLSLstd450Fma = 50,
|
||||
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
|
||||
GLSLstd450FrexpStruct = 52, // no OpVariable operand
|
||||
GLSLstd450Ldexp = 53,
|
||||
|
||||
GLSLstd450PackSnorm4x8 = 54,
|
||||
GLSLstd450PackUnorm4x8 = 55,
|
||||
GLSLstd450PackSnorm2x16 = 56,
|
||||
GLSLstd450PackUnorm2x16 = 57,
|
||||
GLSLstd450PackHalf2x16 = 58,
|
||||
GLSLstd450PackDouble2x32 = 59,
|
||||
GLSLstd450UnpackSnorm2x16 = 60,
|
||||
GLSLstd450UnpackUnorm2x16 = 61,
|
||||
GLSLstd450UnpackHalf2x16 = 62,
|
||||
GLSLstd450UnpackSnorm4x8 = 63,
|
||||
GLSLstd450UnpackUnorm4x8 = 64,
|
||||
GLSLstd450UnpackDouble2x32 = 65,
|
||||
|
||||
GLSLstd450Length = 66,
|
||||
GLSLstd450Distance = 67,
|
||||
GLSLstd450Cross = 68,
|
||||
GLSLstd450Normalize = 69,
|
||||
GLSLstd450FaceForward = 70,
|
||||
GLSLstd450Reflect = 71,
|
||||
GLSLstd450Refract = 72,
|
||||
|
||||
GLSLstd450FindILsb = 73,
|
||||
GLSLstd450FindSMsb = 74,
|
||||
GLSLstd450FindUMsb = 75,
|
||||
|
||||
GLSLstd450InterpolateAtCentroid = 76,
|
||||
GLSLstd450InterpolateAtSample = 77,
|
||||
GLSLstd450InterpolateAtOffset = 78,
|
||||
|
||||
GLSLstd450NMin = 79,
|
||||
GLSLstd450NMax = 80,
|
||||
GLSLstd450NClamp = 81,
|
||||
|
||||
GLSLstd450Count
|
||||
};
|
||||
|
||||
#endif // #ifndef GLSLstd450_H
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Copyright (C) 2014 LunarG, Inc.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
|
||||
#include "SpvTools.h"
|
||||
#include "glslang/Include/intermediate.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
void GetSpirvVersion(std::string&);
|
||||
int GetSpirvGeneratorVersion();
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
SpvOptions* options = nullptr);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
|
||||
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
|
||||
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// Copyright (C) 2016 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GLSLANG_SPIRV_LOGGER_H
|
||||
#define GLSLANG_SPIRV_LOGGER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace spv {
|
||||
|
||||
// A class for holding all SPIR-V build status messages, including
|
||||
// missing/TBD functionalities, warnings, and errors.
|
||||
class SpvBuildLogger {
|
||||
public:
|
||||
SpvBuildLogger() {}
|
||||
|
||||
#ifdef GLSLANG_WEB
|
||||
void tbdFunctionality(const std::string& f) { }
|
||||
void missingFunctionality(const std::string& f) { }
|
||||
void warning(const std::string& w) { }
|
||||
void error(const std::string& e) { errors.push_back(e); }
|
||||
std::string getAllMessages() { return ""; }
|
||||
#else
|
||||
|
||||
// Registers a TBD functionality.
|
||||
void tbdFunctionality(const std::string& f);
|
||||
// Registers a missing functionality.
|
||||
void missingFunctionality(const std::string& f);
|
||||
|
||||
// Logs a warning.
|
||||
void warning(const std::string& w) { warnings.push_back(w); }
|
||||
// Logs an error.
|
||||
void error(const std::string& e) { errors.push_back(e); }
|
||||
|
||||
// Returns all messages accumulated in the order of:
|
||||
// TBD functionalities, missing functionalities, warnings, errors.
|
||||
std::string getAllMessages() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
SpvBuildLogger(const SpvBuildLogger&);
|
||||
|
||||
std::vector<std::string> tbdFeatures;
|
||||
std::vector<std::string> missingFeatures;
|
||||
std::vector<std::string> warnings;
|
||||
std::vector<std::string> errors;
|
||||
};
|
||||
|
||||
} // end spv namespace
|
||||
|
||||
#endif // GLSLANG_SPIRV_LOGGER_H
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2020 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
//
|
||||
|
||||
#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
|
||||
#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
NonSemanticDebugPrintfRevision = 1,
|
||||
NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
|
||||
};
|
||||
|
||||
enum NonSemanticDebugPrintfInstructions {
|
||||
NonSemanticDebugPrintfDebugPrintf = 1,
|
||||
NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
|
||||
|
|
@ -0,0 +1,304 @@
|
|||
//
|
||||
// Copyright (C) 2015 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef SPIRVREMAPPER_H
|
||||
#define SPIRVREMAPPER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
|
||||
namespace spv {
|
||||
|
||||
// MSVC defines __cplusplus as an older value, even when it supports almost all of 11.
|
||||
// We handle that here by making our own symbol.
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||
# define use_cpp11 1
|
||||
#endif
|
||||
|
||||
class spirvbin_base_t
|
||||
{
|
||||
public:
|
||||
enum Options {
|
||||
NONE = 0,
|
||||
STRIP = (1<<0),
|
||||
MAP_TYPES = (1<<1),
|
||||
MAP_NAMES = (1<<2),
|
||||
MAP_FUNCS = (1<<3),
|
||||
DCE_FUNCS = (1<<4),
|
||||
DCE_VARS = (1<<5),
|
||||
DCE_TYPES = (1<<6),
|
||||
OPT_LOADSTORE = (1<<7),
|
||||
OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV
|
||||
MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS),
|
||||
DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES),
|
||||
OPT_ALL = (OPT_LOADSTORE),
|
||||
|
||||
ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL),
|
||||
DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace SPV
|
||||
|
||||
#if !defined (use_cpp11)
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
namespace spv {
|
||||
class spirvbin_t : public spirvbin_base_t
|
||||
{
|
||||
public:
|
||||
spirvbin_t(int /*verbose = 0*/) { }
|
||||
|
||||
void remap(std::vector<std::uint32_t>& /*spv*/, unsigned int /*opts = 0*/)
|
||||
{
|
||||
printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n");
|
||||
exit(5);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace SPV
|
||||
|
||||
#else // defined (use_cpp11)
|
||||
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "spirv.hpp"
|
||||
#include "spvIR.h"
|
||||
|
||||
namespace spv {
|
||||
|
||||
// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
|
||||
class spirvbin_t : public spirvbin_base_t
|
||||
{
|
||||
public:
|
||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)
|
||||
{ }
|
||||
|
||||
virtual ~spirvbin_t() { }
|
||||
|
||||
// remap on an existing binary in memory
|
||||
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
|
||||
|
||||
// Type for error/log handler functions
|
||||
typedef std::function<void(const std::string&)> errorfn_t;
|
||||
typedef std::function<void(const std::string&)> logfn_t;
|
||||
|
||||
// Register error/log handling functions (can be lambda fn / functor / etc)
|
||||
static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
|
||||
static void registerLogHandler(logfn_t handler) { logHandler = handler; }
|
||||
|
||||
protected:
|
||||
// This can be overridden to provide other message behavior if needed
|
||||
virtual void msg(int minVerbosity, int indent, const std::string& txt) const;
|
||||
|
||||
private:
|
||||
// Local to global, or global to local ID map
|
||||
typedef std::unordered_map<spv::Id, spv::Id> idmap_t;
|
||||
typedef std::unordered_set<spv::Id> idset_t;
|
||||
typedef std::unordered_map<spv::Id, int> blockmap_t;
|
||||
|
||||
void remap(std::uint32_t opts = DO_EVERYTHING);
|
||||
|
||||
// Map of names to IDs
|
||||
typedef std::unordered_map<std::string, spv::Id> namemap_t;
|
||||
|
||||
typedef std::uint32_t spirword_t;
|
||||
|
||||
typedef std::pair<unsigned, unsigned> range_t;
|
||||
typedef std::function<void(spv::Id&)> idfn_t;
|
||||
typedef std::function<bool(spv::Op, unsigned start)> instfn_t;
|
||||
|
||||
// Special Values for ID map:
|
||||
static const spv::Id unmapped; // unchanged from default value
|
||||
static const spv::Id unused; // unused ID
|
||||
static const int header_size; // SPIR header = 5 words
|
||||
|
||||
class id_iterator_t;
|
||||
|
||||
// For mapping type entries between different shaders
|
||||
typedef std::vector<spirword_t> typeentry_t;
|
||||
typedef std::map<spv::Id, typeentry_t> globaltypes_t;
|
||||
|
||||
// A set that preserves position order, and a reverse map
|
||||
typedef std::set<int> posmap_t;
|
||||
typedef std::unordered_map<spv::Id, int> posmap_rev_t;
|
||||
|
||||
// Maps and ID to the size of its base type, if known.
|
||||
typedef std::unordered_map<spv::Id, unsigned> typesize_map_t;
|
||||
|
||||
// handle error
|
||||
void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); }
|
||||
|
||||
bool isConstOp(spv::Op opCode) const;
|
||||
bool isTypeOp(spv::Op opCode) const;
|
||||
bool isStripOp(spv::Op opCode) const;
|
||||
bool isFlowCtrl(spv::Op opCode) const;
|
||||
range_t literalRange(spv::Op opCode) const;
|
||||
range_t typeRange(spv::Op opCode) const;
|
||||
range_t constRange(spv::Op opCode) const;
|
||||
unsigned typeSizeInWords(spv::Id id) const;
|
||||
unsigned idTypeSizeInWords(spv::Id id) const;
|
||||
|
||||
spv::Id& asId(unsigned word) { return spv[word]; }
|
||||
const spv::Id& asId(unsigned word) const { return spv[word]; }
|
||||
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
|
||||
std::uint32_t asOpCodeHash(unsigned word);
|
||||
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
|
||||
unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); }
|
||||
spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
|
||||
unsigned idPos(spv::Id id) const;
|
||||
|
||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
||||
|
||||
// Header access & set methods
|
||||
spirword_t magic() const { return spv[0]; } // return magic number
|
||||
spirword_t bound() const { return spv[3]; } // return Id bound from header
|
||||
spirword_t bound(spirword_t b) { return spv[3] = b; }
|
||||
spirword_t genmagic() const { return spv[2]; } // generator magic
|
||||
spirword_t genmagic(spirword_t m) { return spv[2] = m; }
|
||||
spirword_t schemaNum() const { return spv[4]; } // schema number from header
|
||||
|
||||
// Mapping fns: get
|
||||
spv::Id localId(spv::Id id) const { return idMapL[id]; }
|
||||
|
||||
// Mapping fns: set
|
||||
inline spv::Id localId(spv::Id id, spv::Id newId);
|
||||
void countIds(spv::Id id);
|
||||
|
||||
// Return next unused new local ID.
|
||||
// NOTE: boost::dynamic_bitset would be more efficient due to find_next(),
|
||||
// which std::vector<bool> doens't have.
|
||||
inline spv::Id nextUnusedId(spv::Id id);
|
||||
|
||||
void buildLocalMaps();
|
||||
std::string literalString(unsigned word) const; // Return literal as a std::string
|
||||
int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; }
|
||||
|
||||
bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); }
|
||||
bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; }
|
||||
bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; }
|
||||
bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); }
|
||||
bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); }
|
||||
|
||||
// bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const;
|
||||
// spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const;
|
||||
std::uint32_t hashType(unsigned typeStart) const;
|
||||
|
||||
spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0);
|
||||
int processInstruction(unsigned word, instfn_t, idfn_t);
|
||||
|
||||
void validate() const;
|
||||
void mapTypeConst();
|
||||
void mapFnBodies();
|
||||
void optLoadStore();
|
||||
void dceFuncs();
|
||||
void dceVars();
|
||||
void dceTypes();
|
||||
void mapNames();
|
||||
void foldIds(); // fold IDs to smallest space
|
||||
void forwardLoadStores(); // load store forwarding (EXPERIMENTAL)
|
||||
void offsetIds(); // create relative offset IDs
|
||||
|
||||
void applyMap(); // remap per local name map
|
||||
void mapRemainder(); // map any IDs we haven't touched yet
|
||||
void stripDebug(); // strip all debug info
|
||||
void stripDeadRefs(); // strips debug info for now-dead references after DCE
|
||||
void strip(); // remove debug symbols
|
||||
|
||||
std::vector<spirword_t> spv; // SPIR words
|
||||
|
||||
namemap_t nameMap; // ID names from OpName
|
||||
|
||||
// Since we want to also do binary ops, we can't use std::vector<bool>. we could use
|
||||
// boost::dynamic_bitset, but we're trying to avoid a boost dependency.
|
||||
typedef std::uint64_t bits_t;
|
||||
std::vector<bits_t> mapped; // which new IDs have been mapped
|
||||
static const int mBits = sizeof(bits_t) * 4;
|
||||
|
||||
bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); }
|
||||
void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); }
|
||||
void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); }
|
||||
size_t maxMappedId() const { return mapped.size() * mBits; }
|
||||
|
||||
// Add a strip range for a given instruction starting at 'start'
|
||||
// Note: avoiding brace initializers to please older versions os MSVC.
|
||||
void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); }
|
||||
|
||||
// Function start and end. use unordered_map because we'll have
|
||||
// many fewer functions than IDs.
|
||||
std::unordered_map<spv::Id, range_t> fnPos;
|
||||
|
||||
// Which functions are called, anywhere in the module, with a call count
|
||||
std::unordered_map<spv::Id, int> fnCalls;
|
||||
|
||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
||||
posmap_rev_t idPosR; // reverse map from IDs to positions
|
||||
typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known.
|
||||
|
||||
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
|
||||
|
||||
spv::Id entryPoint; // module entry point
|
||||
spv::Id largestNewId; // biggest new ID we have mapped anything to
|
||||
|
||||
// Sections of the binary to strip, given as [begin,end)
|
||||
std::vector<range_t> stripRange;
|
||||
|
||||
// processing options:
|
||||
std::uint32_t options;
|
||||
int verbose; // verbosity level
|
||||
|
||||
// Error latch: this is set if the error handler is ever executed. It would be better to
|
||||
// use a try/catch block and throw, but that's not desired for certain environments, so
|
||||
// this is the alternative.
|
||||
mutable bool errorLatch;
|
||||
|
||||
static errorfn_t errorHandler;
|
||||
static logfn_t logHandler;
|
||||
};
|
||||
|
||||
} // namespace SPV
|
||||
|
||||
#endif // defined (use_cpp11)
|
||||
#endif // SPIRVREMAPPER_H
|
||||
|
|
@ -0,0 +1,863 @@
|
|||
//
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
// Copyright (C) 2015-2020 Google, Inc.
|
||||
// Copyright (C) 2017 ARM Limited.
|
||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// "Builder" is an interface to fully build SPIR-V IR. Allocate one of
|
||||
// these to build (a thread safe) internal SPIR-V representation (IR),
|
||||
// and then dump it as a binary stream according to the SPIR-V specification.
|
||||
//
|
||||
// A Builder has a 1:1 relationship with a SPIR-V module.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef SpvBuilder_H
|
||||
#define SpvBuilder_H
|
||||
|
||||
#include "Logger.h"
|
||||
#include "spirv.hpp"
|
||||
#include "spvIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
||||
namespace spv {
|
||||
|
||||
typedef enum {
|
||||
Spv_1_0 = (1 << 16),
|
||||
Spv_1_1 = (1 << 16) | (1 << 8),
|
||||
Spv_1_2 = (1 << 16) | (2 << 8),
|
||||
Spv_1_3 = (1 << 16) | (3 << 8),
|
||||
Spv_1_4 = (1 << 16) | (4 << 8),
|
||||
Spv_1_5 = (1 << 16) | (5 << 8),
|
||||
} SpvVersion;
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
|
||||
virtual ~Builder();
|
||||
|
||||
static const int maxMatrixSize = 4;
|
||||
|
||||
unsigned int getSpvVersion() const { return spvVersion; }
|
||||
|
||||
void setSource(spv::SourceLanguage lang, int version)
|
||||
{
|
||||
source = lang;
|
||||
sourceVersion = version;
|
||||
}
|
||||
spv::Id getStringId(const std::string& str)
|
||||
{
|
||||
auto sItr = stringIds.find(str);
|
||||
if (sItr != stringIds.end())
|
||||
return sItr->second;
|
||||
spv::Id strId = getUniqueId();
|
||||
Instruction* fileString = new Instruction(strId, NoType, OpString);
|
||||
const char* file_c_str = str.c_str();
|
||||
fileString->addStringOperand(file_c_str);
|
||||
strings.push_back(std::unique_ptr<Instruction>(fileString));
|
||||
module.mapInstruction(fileString);
|
||||
stringIds[file_c_str] = strId;
|
||||
return strId;
|
||||
}
|
||||
void setSourceFile(const std::string& file)
|
||||
{
|
||||
sourceFileStringId = getStringId(file);
|
||||
}
|
||||
void setSourceText(const std::string& text) { sourceText = text; }
|
||||
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
|
||||
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
|
||||
void setEmitOpLines() { emitOpLines = true; }
|
||||
void addExtension(const char* ext) { extensions.insert(ext); }
|
||||
void removeExtension(const char* ext)
|
||||
{
|
||||
extensions.erase(ext);
|
||||
}
|
||||
void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion)
|
||||
{
|
||||
if (getSpvVersion() < static_cast<unsigned>(incorporatedVersion))
|
||||
addExtension(ext);
|
||||
}
|
||||
void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion)
|
||||
{
|
||||
removeExtension(baseExt);
|
||||
addIncorporatedExtension(promoExt, incorporatedVersion);
|
||||
}
|
||||
void addInclude(const std::string& name, const std::string& text)
|
||||
{
|
||||
spv::Id incId = getStringId(name);
|
||||
includeFiles[incId] = &text;
|
||||
}
|
||||
Id import(const char*);
|
||||
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
|
||||
{
|
||||
addressModel = addr;
|
||||
memoryModel = mem;
|
||||
}
|
||||
|
||||
void addCapability(spv::Capability cap) { capabilities.insert(cap); }
|
||||
|
||||
// To get a new <id> for anything needing a new one.
|
||||
Id getUniqueId() { return ++uniqueId; }
|
||||
|
||||
// To get a set of new <id>s, e.g., for a set of function parameters
|
||||
Id getUniqueIds(int numIds)
|
||||
{
|
||||
Id id = uniqueId + 1;
|
||||
uniqueId += numIds;
|
||||
return id;
|
||||
}
|
||||
|
||||
// Generate OpLine for non-filename-based #line directives (ie no filename
|
||||
// seen yet): Log the current line, and if different than the last one,
|
||||
// issue a new OpLine using the new line and current source file name.
|
||||
void setLine(int line);
|
||||
|
||||
// If filename null, generate OpLine for non-filename-based line directives,
|
||||
// else do filename-based: Log the current line and file, and if different
|
||||
// than the last one, issue a new OpLine using the new line and file
|
||||
// name.
|
||||
void setLine(int line, const char* filename);
|
||||
// Low-level OpLine. See setLine() for a layered helper.
|
||||
void addLine(Id fileName, int line, int column);
|
||||
|
||||
// For creating new types (will return old type if the requested one was already made).
|
||||
Id makeVoidType();
|
||||
Id makeBoolType();
|
||||
Id makePointer(StorageClass, Id pointee);
|
||||
Id makeForwardPointer(StorageClass);
|
||||
Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
|
||||
Id makeIntegerType(int width, bool hasSign); // generic
|
||||
Id makeIntType(int width) { return makeIntegerType(width, true); }
|
||||
Id makeUintType(int width) { return makeIntegerType(width, false); }
|
||||
Id makeFloatType(int width);
|
||||
Id makeStructType(const std::vector<Id>& members, const char*);
|
||||
Id makeStructResultType(Id type0, Id type1);
|
||||
Id makeVectorType(Id component, int size);
|
||||
Id makeMatrixType(Id component, int cols, int rows);
|
||||
Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration
|
||||
Id makeRuntimeArray(Id element);
|
||||
Id makeFunctionType(Id returnType, const std::vector<Id>& paramTypes);
|
||||
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
|
||||
Id makeSamplerType();
|
||||
Id makeSampledImageType(Id imageType);
|
||||
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
|
||||
|
||||
// accelerationStructureNV type
|
||||
Id makeAccelerationStructureType();
|
||||
// rayQueryEXT type
|
||||
Id makeRayQueryType();
|
||||
|
||||
// For querying about types.
|
||||
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
|
||||
Id getDerefTypeId(Id resultId) const;
|
||||
Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
|
||||
Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
|
||||
Op getMostBasicTypeClass(Id typeId) const;
|
||||
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
||||
int getNumTypeConstituents(Id typeId) const;
|
||||
int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
|
||||
Id getScalarTypeId(Id typeId) const;
|
||||
Id getContainedTypeId(Id typeId) const;
|
||||
Id getContainedTypeId(Id typeId, int) const;
|
||||
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
|
||||
ImageFormat getImageTypeFormat(Id typeId) const
|
||||
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
|
||||
|
||||
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
|
||||
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
|
||||
bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
|
||||
bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
|
||||
bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); }
|
||||
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
|
||||
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
|
||||
|
||||
bool isBoolType(Id typeId)
|
||||
{ return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
|
||||
bool isIntType(Id typeId) const
|
||||
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
|
||||
bool isUintType(Id typeId) const
|
||||
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
|
||||
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
|
||||
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
|
||||
bool isScalarType(Id typeId) const
|
||||
{ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
|
||||
getTypeClass(typeId) == OpTypeBool; }
|
||||
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
|
||||
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
|
||||
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
|
||||
bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; }
|
||||
#ifdef GLSLANG_WEB
|
||||
bool isCooperativeMatrixType(Id typeId)const { return false; }
|
||||
#else
|
||||
bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
|
||||
#endif
|
||||
bool isAggregateType(Id typeId) const
|
||||
{ return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
|
||||
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
|
||||
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
|
||||
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
|
||||
bool containsType(Id typeId, Op typeOp, unsigned int width) const;
|
||||
bool containsPhysicalStorageBufferOrArray(Id typeId) const;
|
||||
|
||||
bool isConstantOpCode(Op opcode) const;
|
||||
bool isSpecConstantOpCode(Op opcode) const;
|
||||
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
|
||||
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
|
||||
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
|
||||
unsigned int getConstantScalar(Id resultId) const
|
||||
{ return module.getInstruction(resultId)->getImmediateOperand(0); }
|
||||
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
|
||||
|
||||
bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; }
|
||||
bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); }
|
||||
bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; }
|
||||
bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); }
|
||||
// See if a resultId is valid for use as an initializer.
|
||||
bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); }
|
||||
|
||||
int getScalarTypeWidth(Id typeId) const
|
||||
{
|
||||
Id scalarTypeId = getScalarTypeId(typeId);
|
||||
assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat);
|
||||
return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
|
||||
}
|
||||
|
||||
int getTypeNumColumns(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
return getNumTypeConstituents(typeId);
|
||||
}
|
||||
int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
|
||||
int getTypeNumRows(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
return getNumTypeComponents(getContainedTypeId(typeId));
|
||||
}
|
||||
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
||||
|
||||
Dim getTypeDimensionality(Id typeId) const
|
||||
{
|
||||
assert(isImageType(typeId));
|
||||
return (Dim)module.getInstruction(typeId)->getImmediateOperand(1);
|
||||
}
|
||||
Id getImageType(Id resultId) const
|
||||
{
|
||||
Id typeId = getTypeId(resultId);
|
||||
assert(isImageType(typeId) || isSampledImageType(typeId));
|
||||
return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId;
|
||||
}
|
||||
bool isArrayedImageType(Id typeId) const
|
||||
{
|
||||
assert(isImageType(typeId));
|
||||
return module.getInstruction(typeId)->getImmediateOperand(3) != 0;
|
||||
}
|
||||
|
||||
// For making new constants (will return old constant if the requested one was already made).
|
||||
Id makeNullConstant(Id typeId);
|
||||
Id makeBoolConstant(bool b, bool specConstant = false);
|
||||
Id makeInt8Constant(int i, bool specConstant = false)
|
||||
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
|
||||
Id makeUint8Constant(unsigned u, bool specConstant = false)
|
||||
{ return makeIntConstant(makeUintType(8), u, specConstant); }
|
||||
Id makeInt16Constant(int i, bool specConstant = false)
|
||||
{ return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
|
||||
Id makeUint16Constant(unsigned u, bool specConstant = false)
|
||||
{ return makeIntConstant(makeUintType(16), u, specConstant); }
|
||||
Id makeIntConstant(int i, bool specConstant = false)
|
||||
{ return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
|
||||
Id makeUintConstant(unsigned u, bool specConstant = false)
|
||||
{ return makeIntConstant(makeUintType(32), u, specConstant); }
|
||||
Id makeInt64Constant(long long i, bool specConstant = false)
|
||||
{ return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
|
||||
Id makeUint64Constant(unsigned long long u, bool specConstant = false)
|
||||
{ return makeInt64Constant(makeUintType(64), u, specConstant); }
|
||||
Id makeFloatConstant(float f, bool specConstant = false);
|
||||
Id makeDoubleConstant(double d, bool specConstant = false);
|
||||
Id makeFloat16Constant(float f16, bool specConstant = false);
|
||||
Id makeFpConstant(Id type, double d, bool specConstant = false);
|
||||
|
||||
// Turn the array of constants into a proper spv constant of the requested type.
|
||||
Id makeCompositeConstant(Id type, const std::vector<Id>& comps, bool specConst = false);
|
||||
|
||||
// Methods for adding information outside the CFG.
|
||||
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
|
||||
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
|
||||
void addExecutionMode(Function*, ExecutionMode mode, const std::vector<unsigned>& literals);
|
||||
void addExecutionModeId(Function*, ExecutionMode mode, const std::vector<Id>& operandIds);
|
||||
void addName(Id, const char* name);
|
||||
void addMemberName(Id, int member, const char* name);
|
||||
void addDecoration(Id, Decoration, int num = -1);
|
||||
void addDecoration(Id, Decoration, const char*);
|
||||
void addDecoration(Id, Decoration, const std::vector<unsigned>& literals);
|
||||
void addDecoration(Id, Decoration, const std::vector<const char*>& strings);
|
||||
void addDecorationId(Id id, Decoration, Id idDecoration);
|
||||
void addDecorationId(Id id, Decoration, const std::vector<Id>& operandIds);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
|
||||
|
||||
// At the end of what block do the next create*() instructions go?
|
||||
void setBuildPoint(Block* bp) { buildPoint = bp; }
|
||||
Block* getBuildPoint() const { return buildPoint; }
|
||||
|
||||
// Make the entry-point function. The returned pointer is only valid
|
||||
// for the lifetime of this builder.
|
||||
Function* makeEntryPoint(const char*);
|
||||
|
||||
// Make a shader-style function, and create its entry block if entry is non-zero.
|
||||
// Return the function, pass back the entry.
|
||||
// The returned pointer is only valid for the lifetime of this builder.
|
||||
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
|
||||
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
|
||||
|
||||
// Create a return. An 'implicit' return is one not appearing in the source
|
||||
// code. In the case of an implicit return, no post-return block is inserted.
|
||||
void makeReturn(bool implicit, Id retVal = 0);
|
||||
|
||||
// Generate all the code needed to finish up a function.
|
||||
void leaveFunction();
|
||||
|
||||
// Create block terminator instruction for certain statements like
|
||||
// discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT
|
||||
void makeStatementTerminator(spv::Op opcode, const char *name);
|
||||
|
||||
// Create a global or function local or IO variable.
|
||||
Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
|
||||
Id initializer = NoResult);
|
||||
|
||||
// Create an intermediate with an undefined value.
|
||||
Id createUndefined(Id type);
|
||||
|
||||
// Store into an Id and return the l-value
|
||||
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
||||
|
||||
// Load from an Id and return it
|
||||
Id createLoad(Id lValue, spv::Decoration precision,
|
||||
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
||||
|
||||
// Create an OpAccessChain instruction
|
||||
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
|
||||
|
||||
// Create an OpArrayLength instruction
|
||||
Id createArrayLength(Id base, unsigned int member);
|
||||
|
||||
// Create an OpCooperativeMatrixLengthNV instruction
|
||||
Id createCooperativeMatrixLength(Id type);
|
||||
|
||||
// Create an OpCompositeExtract instruction
|
||||
Id createCompositeExtract(Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes);
|
||||
|
||||
Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
|
||||
Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
|
||||
|
||||
void createNoResultOp(Op);
|
||||
void createNoResultOp(Op, Id operand);
|
||||
void createNoResultOp(Op, const std::vector<Id>& operands);
|
||||
void createNoResultOp(Op, const std::vector<IdImmediate>& operands);
|
||||
void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
|
||||
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
|
||||
Id createUnaryOp(Op, Id typeId, Id operand);
|
||||
Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
|
||||
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
|
||||
Id createOp(Op, Id typeId, const std::vector<IdImmediate>& operands);
|
||||
Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
|
||||
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
|
||||
|
||||
// Take an rvalue (source) and a set of channels to extract from it to
|
||||
// make a new rvalue, which is returned.
|
||||
Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels);
|
||||
|
||||
// Take a copy of an lvalue (target) and a source of components, and set the
|
||||
// source components into the lvalue where the 'channels' say to put them.
|
||||
// An updated version of the target is returned.
|
||||
// (No true lvalue or stores are used.)
|
||||
Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels);
|
||||
|
||||
// If both the id and precision are valid, the id
|
||||
// gets tagged with the requested precision.
|
||||
// The passed in id is always the returned id, to simplify use patterns.
|
||||
Id setPrecision(Id id, Decoration precision)
|
||||
{
|
||||
if (precision != NoPrecision && id != NoResult)
|
||||
addDecoration(id, precision);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// Can smear a scalar to a vector for the following forms:
|
||||
// - promoteScalar(scalar, vector) // smear scalar to width of vector
|
||||
// - promoteScalar(vector, scalar) // smear scalar to width of vector
|
||||
// - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to
|
||||
// - promoteScalar(scalar, scalar) // do nothing
|
||||
// Other forms are not allowed.
|
||||
//
|
||||
// Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'.
|
||||
// The type of the created vector is a vector of components of the same type as the scalar.
|
||||
//
|
||||
// Note: One of the arguments will change, with the result coming back that way rather than
|
||||
// through the return value.
|
||||
void promoteScalar(Decoration precision, Id& left, Id& right);
|
||||
|
||||
// Make a value by smearing the scalar to fill the type.
|
||||
// vectorType should be the correct type for making a vector of scalarVal.
|
||||
// (No conversions are done.)
|
||||
Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
|
||||
|
||||
// Create a call to a built-in function.
|
||||
Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args);
|
||||
|
||||
// List of parameters used to create a texture operation
|
||||
struct TextureParameters {
|
||||
Id sampler;
|
||||
Id coords;
|
||||
Id bias;
|
||||
Id lod;
|
||||
Id Dref;
|
||||
Id offset;
|
||||
Id offsets;
|
||||
Id gradX;
|
||||
Id gradY;
|
||||
Id sample;
|
||||
Id component;
|
||||
Id texelOut;
|
||||
Id lodClamp;
|
||||
Id granularity;
|
||||
Id coarse;
|
||||
bool nonprivate;
|
||||
bool volatil;
|
||||
};
|
||||
|
||||
// Select the correct texture operation based on all inputs, and emit the correct instruction
|
||||
Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
|
||||
bool noImplicit, const TextureParameters&, ImageOperandsMask);
|
||||
|
||||
// Emit the OpTextureQuery* instruction that was passed in.
|
||||
// Figure out the right return value and type, and return it.
|
||||
Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult);
|
||||
|
||||
Id createSamplePositionCall(Decoration precision, Id, Id);
|
||||
|
||||
Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned);
|
||||
Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
|
||||
|
||||
// Reduction comparison for composites: For equal and not-equal resulting in a scalar.
|
||||
Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
|
||||
|
||||
// OpCompositeConstruct
|
||||
Id createCompositeConstruct(Id typeId, const std::vector<Id>& constituents);
|
||||
|
||||
// vector or scalar constructor
|
||||
Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
|
||||
|
||||
// matrix constructor
|
||||
Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id constructee);
|
||||
|
||||
// Helper to use for building nested control flow with if-then-else.
|
||||
class If {
|
||||
public:
|
||||
If(Id condition, unsigned int ctrl, Builder& builder);
|
||||
~If() {}
|
||||
|
||||
void makeBeginElse();
|
||||
void makeEndIf();
|
||||
|
||||
private:
|
||||
If(const If&);
|
||||
If& operator=(If&);
|
||||
|
||||
Builder& builder;
|
||||
Id condition;
|
||||
unsigned int control;
|
||||
Function* function;
|
||||
Block* headerBlock;
|
||||
Block* thenBlock;
|
||||
Block* elseBlock;
|
||||
Block* mergeBlock;
|
||||
};
|
||||
|
||||
// Make a switch statement. A switch has 'numSegments' of pieces of code, not containing
|
||||
// any case/default labels, all separated by one or more case/default labels. Each possible
|
||||
// case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this
|
||||
// number space. How to compute the value is given by 'condition', as in switch(condition).
|
||||
//
|
||||
// The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches.
|
||||
//
|
||||
// Use a defaultSegment < 0 if there is no default segment (to branch to post switch).
|
||||
//
|
||||
// Returns the right set of basic blocks to start each code segment with, so that the caller's
|
||||
// recursion stack can hold the memory for it.
|
||||
//
|
||||
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
||||
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
|
||||
|
||||
// Add a branch to the innermost switch's merge block.
|
||||
void addSwitchBreak();
|
||||
|
||||
// Move to the next code segment, passing in the return argument in makeSwitch()
|
||||
void nextSwitchSegment(std::vector<Block*>& segmentBB, int segment);
|
||||
|
||||
// Finish off the innermost switch.
|
||||
void endSwitch(std::vector<Block*>& segmentBB);
|
||||
|
||||
struct LoopBlocks {
|
||||
LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) :
|
||||
head(head), body(body), merge(merge), continue_target(continue_target) { }
|
||||
Block &head, &body, &merge, &continue_target;
|
||||
private:
|
||||
LoopBlocks();
|
||||
LoopBlocks& operator=(const LoopBlocks&) = delete;
|
||||
};
|
||||
|
||||
// Start a new loop and prepare the builder to generate code for it. Until
|
||||
// closeLoop() is called for this loop, createLoopContinue() and
|
||||
// createLoopExit() will target its corresponding blocks.
|
||||
LoopBlocks& makeNewLoop();
|
||||
|
||||
// Create a new block in the function containing the build point. Memory is
|
||||
// owned by the function object.
|
||||
Block& makeNewBlock();
|
||||
|
||||
// Add a branch to the continue_target of the current (innermost) loop.
|
||||
void createLoopContinue();
|
||||
|
||||
// Add an exit (e.g. "break") from the innermost loop that we're currently
|
||||
// in.
|
||||
void createLoopExit();
|
||||
|
||||
// Close the innermost loop that you're in
|
||||
void closeLoop();
|
||||
|
||||
//
|
||||
// Access chain design for an R-Value vs. L-Value:
|
||||
//
|
||||
// There is a single access chain the builder is building at
|
||||
// any particular time. Such a chain can be used to either to a load or
|
||||
// a store, when desired.
|
||||
//
|
||||
// Expressions can be r-values, l-values, or both, or only r-values:
|
||||
// a[b.c].d = .... // l-value
|
||||
// ... = a[b.c].d; // r-value, that also looks like an l-value
|
||||
// ++a[b.c].d; // r-value and l-value
|
||||
// (x + y)[2]; // r-value only, can't possibly be l-value
|
||||
//
|
||||
// Computing an r-value means generating code. Hence,
|
||||
// r-values should only be computed when they are needed, not speculatively.
|
||||
//
|
||||
// Computing an l-value means saving away information for later use in the compiler,
|
||||
// no code is generated until the l-value is later dereferenced. It is okay
|
||||
// to speculatively generate an l-value, just not okay to speculatively dereference it.
|
||||
//
|
||||
// The base of the access chain (the left-most variable or expression
|
||||
// from which everything is based) can be set either as an l-value
|
||||
// or as an r-value. Most efficient would be to set an l-value if one
|
||||
// is available. If an expression was evaluated, the resulting r-value
|
||||
// can be set as the chain base.
|
||||
//
|
||||
// The users of this single access chain can save and restore if they
|
||||
// want to nest or manage multiple chains.
|
||||
//
|
||||
|
||||
struct AccessChain {
|
||||
Id base; // for l-values, pointer to the base object, for r-values, the base object
|
||||
std::vector<Id> indexChain;
|
||||
Id instr; // cache the instruction that generates this access chain
|
||||
std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
|
||||
Id component; // a dynamic component index, can coexist with a swizzle,
|
||||
// done after the swizzle, NoResult if not present
|
||||
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied;
|
||||
// NoType unless a swizzle or component is present
|
||||
bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
|
||||
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment.
|
||||
// Only tracks base and (optional) component selection alignment.
|
||||
|
||||
// Accumulate whether anything in the chain of structures has coherent decorations.
|
||||
struct CoherentFlags {
|
||||
CoherentFlags() { clear(); }
|
||||
#ifdef GLSLANG_WEB
|
||||
void clear() { }
|
||||
bool isVolatile() const { return false; }
|
||||
CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
|
||||
#else
|
||||
bool isVolatile() const { return volatil; }
|
||||
bool isNonUniform() const { return nonUniform; }
|
||||
bool anyCoherent() const {
|
||||
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
|
||||
subgroupcoherent || shadercallcoherent;
|
||||
}
|
||||
|
||||
unsigned coherent : 1;
|
||||
unsigned devicecoherent : 1;
|
||||
unsigned queuefamilycoherent : 1;
|
||||
unsigned workgroupcoherent : 1;
|
||||
unsigned subgroupcoherent : 1;
|
||||
unsigned shadercallcoherent : 1;
|
||||
unsigned nonprivate : 1;
|
||||
unsigned volatil : 1;
|
||||
unsigned isImage : 1;
|
||||
unsigned nonUniform : 1;
|
||||
|
||||
void clear() {
|
||||
coherent = 0;
|
||||
devicecoherent = 0;
|
||||
queuefamilycoherent = 0;
|
||||
workgroupcoherent = 0;
|
||||
subgroupcoherent = 0;
|
||||
shadercallcoherent = 0;
|
||||
nonprivate = 0;
|
||||
volatil = 0;
|
||||
isImage = 0;
|
||||
nonUniform = 0;
|
||||
}
|
||||
|
||||
CoherentFlags operator |=(const CoherentFlags &other) {
|
||||
coherent |= other.coherent;
|
||||
devicecoherent |= other.devicecoherent;
|
||||
queuefamilycoherent |= other.queuefamilycoherent;
|
||||
workgroupcoherent |= other.workgroupcoherent;
|
||||
subgroupcoherent |= other.subgroupcoherent;
|
||||
shadercallcoherent |= other.shadercallcoherent;
|
||||
nonprivate |= other.nonprivate;
|
||||
volatil |= other.volatil;
|
||||
isImage |= other.isImage;
|
||||
nonUniform |= other.nonUniform;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
CoherentFlags coherentFlags;
|
||||
};
|
||||
|
||||
//
|
||||
// the SPIR-V builder maintains a single active chain that
|
||||
// the following methods operate on
|
||||
//
|
||||
|
||||
// for external save and restore
|
||||
AccessChain getAccessChain() { return accessChain; }
|
||||
void setAccessChain(AccessChain newChain) { accessChain = newChain; }
|
||||
|
||||
// clear accessChain
|
||||
void clearAccessChain();
|
||||
|
||||
// set new base as an l-value base
|
||||
void setAccessChainLValue(Id lValue)
|
||||
{
|
||||
assert(isPointer(lValue));
|
||||
accessChain.base = lValue;
|
||||
}
|
||||
|
||||
// set new base value as an r-value
|
||||
void setAccessChainRValue(Id rValue)
|
||||
{
|
||||
accessChain.isRValue = true;
|
||||
accessChain.base = rValue;
|
||||
}
|
||||
|
||||
// push offset onto the end of the chain
|
||||
void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
|
||||
{
|
||||
accessChain.indexChain.push_back(offset);
|
||||
accessChain.coherentFlags |= coherentFlags;
|
||||
accessChain.alignment |= alignment;
|
||||
}
|
||||
|
||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
|
||||
AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
|
||||
|
||||
// push a dynamic component selection onto the access chain, only applicable with a
|
||||
// non-trivial swizzle or no swizzle
|
||||
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
|
||||
unsigned int alignment)
|
||||
{
|
||||
if (accessChain.swizzle.size() != 1) {
|
||||
accessChain.component = component;
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
}
|
||||
accessChain.coherentFlags |= coherentFlags;
|
||||
accessChain.alignment |= alignment;
|
||||
}
|
||||
|
||||
// use accessChain and swizzle to store value
|
||||
void accessChainStore(Id rvalue, Decoration nonUniform,
|
||||
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
||||
|
||||
// use accessChain and swizzle to load an r-value
|
||||
Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType,
|
||||
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
|
||||
unsigned int alignment = 0);
|
||||
|
||||
// Return whether or not the access chain can be represented in SPIR-V
|
||||
// as an l-value.
|
||||
// E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
|
||||
bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
|
||||
|
||||
// get the direct pointer for an l-value
|
||||
Id accessChainGetLValue();
|
||||
|
||||
// Get the inferred SPIR-V type of the result of the current access chain,
|
||||
// based on the type of the base and the chain of dereferences.
|
||||
Id accessChainGetInferredType();
|
||||
|
||||
// Add capabilities, extensions, remove unneeded decorations, etc.,
|
||||
// based on the resulting SPIR-V.
|
||||
void postProcess();
|
||||
|
||||
// Prune unreachable blocks in the CFG and remove unneeded decorations.
|
||||
void postProcessCFG();
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
// Add capabilities, extensions based on instructions in the module.
|
||||
void postProcessFeatures();
|
||||
// Hook to visit each instruction in a block in a function
|
||||
void postProcess(Instruction&);
|
||||
// Hook to visit each non-32-bit sized float/int operation in a block.
|
||||
void postProcessType(const Instruction&, spv::Id typeId);
|
||||
#endif
|
||||
|
||||
void dump(std::vector<unsigned int>&) const;
|
||||
|
||||
void createBranch(Block* block);
|
||||
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
||||
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
|
||||
const std::vector<unsigned int>& operands);
|
||||
|
||||
// Sets to generate opcode for specialization constants.
|
||||
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
|
||||
// Sets to generate opcode for non-specialization constants (normal mode).
|
||||
void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; }
|
||||
// Check if the builder is generating code for spec constants.
|
||||
bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
|
||||
|
||||
protected:
|
||||
Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
|
||||
Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
|
||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value);
|
||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2);
|
||||
Id findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps);
|
||||
Id findStructConstant(Id typeId, const std::vector<Id>& comps);
|
||||
Id collapseAccessChain();
|
||||
void remapDynamicSwizzle();
|
||||
void transferAccessChainSwizzle(bool dynamic);
|
||||
void simplifyAccessChainSwizzle();
|
||||
void createAndSetNoPredecessorBlock(const char*);
|
||||
void createSelectionMerge(Block* mergeBlock, unsigned int control);
|
||||
void dumpSourceInstructions(std::vector<unsigned int>&) const;
|
||||
void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
|
||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
|
||||
void dumpModuleProcesses(std::vector<unsigned int>&) const;
|
||||
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
|
||||
const;
|
||||
|
||||
unsigned int spvVersion; // the version of SPIR-V to emit in the header
|
||||
SourceLanguage source;
|
||||
int sourceVersion;
|
||||
spv::Id sourceFileStringId;
|
||||
std::string sourceText;
|
||||
int currentLine;
|
||||
const char* currentFile;
|
||||
bool emitOpLines;
|
||||
std::set<std::string> extensions;
|
||||
std::vector<const char*> sourceExtensions;
|
||||
std::vector<const char*> moduleProcesses;
|
||||
AddressingModel addressModel;
|
||||
MemoryModel memoryModel;
|
||||
std::set<spv::Capability> capabilities;
|
||||
int builderNumber;
|
||||
Module module;
|
||||
Block* buildPoint;
|
||||
Id uniqueId;
|
||||
Function* entryPointFunction;
|
||||
bool generatingOpCodeForSpecConst;
|
||||
AccessChain accessChain;
|
||||
|
||||
// special blocks of instructions for output
|
||||
std::vector<std::unique_ptr<Instruction> > strings;
|
||||
std::vector<std::unique_ptr<Instruction> > imports;
|
||||
std::vector<std::unique_ptr<Instruction> > entryPoints;
|
||||
std::vector<std::unique_ptr<Instruction> > executionModes;
|
||||
std::vector<std::unique_ptr<Instruction> > names;
|
||||
std::vector<std::unique_ptr<Instruction> > decorations;
|
||||
std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
|
||||
std::vector<std::unique_ptr<Instruction> > externals;
|
||||
std::vector<std::unique_ptr<Function> > functions;
|
||||
|
||||
// not output, internally used for quick & dirty canonical (unique) creation
|
||||
|
||||
// map type opcodes to constant inst.
|
||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
|
||||
// map struct-id to constant instructions
|
||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
|
||||
// map type opcodes to type instructions
|
||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
|
||||
// list of OpConstantNull instructions
|
||||
std::vector<Instruction*> nullConstants;
|
||||
|
||||
// stack of switches
|
||||
std::stack<Block*> switchMerges;
|
||||
|
||||
// Our loop stack.
|
||||
std::stack<LoopBlocks> loops;
|
||||
|
||||
// map from strings to their string ids
|
||||
std::unordered_map<std::string, spv::Id> stringIds;
|
||||
|
||||
// map from include file name ids to their contents
|
||||
std::map<spv::Id, const std::string*> includeFiles;
|
||||
|
||||
// The stream for outputting warnings and errors.
|
||||
SpvBuildLogger* logger;
|
||||
}; // end Builder class
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
#endif // SpvBuilder_H
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// Copyright (C) 2014-2016 LunarG, Inc.
|
||||
// Copyright (C) 2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Call into SPIRV-Tools to disassemble, validate, and optimize.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef GLSLANG_SPV_TOOLS_H
|
||||
#define GLSLANG_SPV_TOOLS_H
|
||||
|
||||
#if ENABLE_OPT
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#endif
|
||||
|
||||
#include "glslang/MachineIndependent/localintermediate.h"
|
||||
#include "Logger.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
struct SpvOptions {
|
||||
SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
|
||||
optimizeSize(false), disassemble(false), validate(false) { }
|
||||
bool generateDebugInfo;
|
||||
bool stripDebugInfo;
|
||||
bool disableOptimizer;
|
||||
bool optimizeSize;
|
||||
bool disassemble;
|
||||
bool validate;
|
||||
};
|
||||
|
||||
#if ENABLE_OPT
|
||||
|
||||
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
|
||||
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
|
||||
|
||||
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
|
||||
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
|
||||
spv_target_env requested_context);
|
||||
|
||||
// Apply the SPIRV-Tools validator to generated SPIR-V.
|
||||
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
spv::SpvBuildLogger*, bool prelegalization);
|
||||
|
||||
// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
|
||||
void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
spv::SpvBuildLogger*, const SpvOptions*);
|
||||
|
||||
// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
|
||||
// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
|
||||
// optimization is disabled.
|
||||
void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
|
||||
std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // GLSLANG_SPV_TOOLS_H
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_UTIL_BITUTILS_H_
|
||||
#define LIBSPIRV_UTIL_BITUTILS_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace spvutils {
|
||||
|
||||
// Performs a bitwise copy of source to the destination type Dest.
|
||||
template <typename Dest, typename Src>
|
||||
Dest BitwiseCast(Src source) {
|
||||
Dest dest;
|
||||
static_assert(sizeof(source) == sizeof(dest),
|
||||
"BitwiseCast: Source and destination must have the same size");
|
||||
std::memcpy(static_cast<void*>(&dest), &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
// SetBits<T, First, Num> returns an integer of type <T> with bits set
|
||||
// for position <First> through <First + Num - 1>, counting from the least
|
||||
// significant bit. In particular when Num == 0, no positions are set to 1.
|
||||
// A static assert will be triggered if First + Num > sizeof(T) * 8, that is,
|
||||
// a bit that will not fit in the underlying type is set.
|
||||
template <typename T, size_t First = 0, size_t Num = 0>
|
||||
struct SetBits {
|
||||
static_assert(First < sizeof(T) * 8,
|
||||
"Tried to set a bit that is shifted too far.");
|
||||
const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
|
||||
};
|
||||
|
||||
template <typename T, size_t Last>
|
||||
struct SetBits<T, Last, 0> {
|
||||
const static T get = T(0);
|
||||
};
|
||||
|
||||
// This is all compile-time so we can put our tests right here.
|
||||
static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
|
||||
"SetBits failed");
|
||||
|
||||
static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
|
||||
"SetBits failed");
|
||||
|
||||
} // namespace spvutils
|
||||
|
||||
#endif // LIBSPIRV_UTIL_BITUTILS_H_
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Disassembler for SPIR-V.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef disassembler_H
|
||||
#define disassembler_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace spv {
|
||||
|
||||
// disassemble with glslang custom disassembler
|
||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
|
||||
|
||||
} // end namespace spv
|
||||
|
||||
#endif // disassembler_H
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
//
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Parameterize the SPIR-V enumerants.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace spv {
|
||||
|
||||
// Fill in all the parameters
|
||||
void Parameterize();
|
||||
|
||||
// Return the English names of all the enums.
|
||||
const char* SourceString(int);
|
||||
const char* AddressingString(int);
|
||||
const char* MemoryString(int);
|
||||
const char* ExecutionModelString(int);
|
||||
const char* ExecutionModeString(int);
|
||||
const char* StorageClassString(int);
|
||||
const char* DecorationString(int);
|
||||
const char* BuiltInString(int);
|
||||
const char* DimensionString(int);
|
||||
const char* SelectControlString(int);
|
||||
const char* LoopControlString(int);
|
||||
const char* FunctionControlString(int);
|
||||
const char* SamplerAddressingModeString(int);
|
||||
const char* SamplerFilterModeString(int);
|
||||
const char* ImageFormatString(int);
|
||||
const char* ImageChannelOrderString(int);
|
||||
const char* ImageChannelTypeString(int);
|
||||
const char* ImageChannelDataTypeString(int type);
|
||||
const char* ImageOperandsString(int format);
|
||||
const char* ImageOperands(int);
|
||||
const char* FPFastMathString(int);
|
||||
const char* FPRoundingModeString(int);
|
||||
const char* LinkageTypeString(int);
|
||||
const char* FuncParamAttrString(int);
|
||||
const char* AccessQualifierString(int);
|
||||
const char* MemorySemanticsString(int);
|
||||
const char* MemoryAccessString(int);
|
||||
const char* ExecutionScopeString(int);
|
||||
const char* GroupOperationString(int);
|
||||
const char* KernelEnqueueFlagsString(int);
|
||||
const char* KernelProfilingInfoString(int);
|
||||
const char* CapabilityString(int);
|
||||
const char* OpcodeString(int);
|
||||
const char* ScopeString(int mem);
|
||||
|
||||
// For grouping opcodes into subsections
|
||||
enum OpcodeClass {
|
||||
OpClassMisc,
|
||||
OpClassDebug,
|
||||
OpClassAnnotate,
|
||||
OpClassExtension,
|
||||
OpClassMode,
|
||||
OpClassType,
|
||||
OpClassConstant,
|
||||
OpClassMemory,
|
||||
OpClassFunction,
|
||||
OpClassImage,
|
||||
OpClassConvert,
|
||||
OpClassComposite,
|
||||
OpClassArithmetic,
|
||||
OpClassBit,
|
||||
OpClassRelationalLogical,
|
||||
OpClassDerivative,
|
||||
OpClassFlowControl,
|
||||
OpClassAtomic,
|
||||
OpClassPrimitive,
|
||||
OpClassBarrier,
|
||||
OpClassGroup,
|
||||
OpClassDeviceSideEnqueue,
|
||||
OpClassPipe,
|
||||
|
||||
OpClassCount,
|
||||
OpClassMissing // all instructions start out as missing
|
||||
};
|
||||
|
||||
// For parameterizing operands.
|
||||
enum OperandClass {
|
||||
OperandNone,
|
||||
OperandId,
|
||||
OperandVariableIds,
|
||||
OperandOptionalLiteral,
|
||||
OperandOptionalLiteralString,
|
||||
OperandVariableLiterals,
|
||||
OperandVariableIdLiteral,
|
||||
OperandVariableLiteralId,
|
||||
OperandLiteralNumber,
|
||||
OperandLiteralString,
|
||||
OperandVariableLiteralStrings,
|
||||
OperandSource,
|
||||
OperandExecutionModel,
|
||||
OperandAddressing,
|
||||
OperandMemory,
|
||||
OperandExecutionMode,
|
||||
OperandStorage,
|
||||
OperandDimensionality,
|
||||
OperandSamplerAddressingMode,
|
||||
OperandSamplerFilterMode,
|
||||
OperandSamplerImageFormat,
|
||||
OperandImageChannelOrder,
|
||||
OperandImageChannelDataType,
|
||||
OperandImageOperands,
|
||||
OperandFPFastMath,
|
||||
OperandFPRoundingMode,
|
||||
OperandLinkageType,
|
||||
OperandAccessQualifier,
|
||||
OperandFuncParamAttr,
|
||||
OperandDecoration,
|
||||
OperandBuiltIn,
|
||||
OperandSelect,
|
||||
OperandLoop,
|
||||
OperandFunction,
|
||||
OperandMemorySemantics,
|
||||
OperandMemoryAccess,
|
||||
OperandScope,
|
||||
OperandGroupOperation,
|
||||
OperandKernelEnqueueFlags,
|
||||
OperandKernelProfilingInfo,
|
||||
OperandCapability,
|
||||
|
||||
OperandOpcode,
|
||||
|
||||
OperandCount
|
||||
};
|
||||
|
||||
// Any specific enum can have a set of capabilities that allow it:
|
||||
typedef std::vector<Capability> EnumCaps;
|
||||
|
||||
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
||||
class OperandParameters {
|
||||
public:
|
||||
OperandParameters() { }
|
||||
void push(OperandClass oc, const char* d, bool opt = false)
|
||||
{
|
||||
opClass.push_back(oc);
|
||||
desc.push_back(d);
|
||||
optional.push_back(opt);
|
||||
}
|
||||
void setOptional();
|
||||
OperandClass getClass(int op) const { return opClass[op]; }
|
||||
const char* getDesc(int op) const { return desc[op]; }
|
||||
bool isOptional(int op) const { return optional[op]; }
|
||||
int getNum() const { return (int)opClass.size(); }
|
||||
|
||||
protected:
|
||||
std::vector<OperandClass> opClass;
|
||||
std::vector<const char*> desc;
|
||||
std::vector<bool> optional;
|
||||
};
|
||||
|
||||
// Parameterize an enumerant
|
||||
class EnumParameters {
|
||||
public:
|
||||
EnumParameters() : desc(0) { }
|
||||
const char* desc;
|
||||
};
|
||||
|
||||
// Parameterize a set of enumerants that form an enum
|
||||
class EnumDefinition : public EnumParameters {
|
||||
public:
|
||||
EnumDefinition() :
|
||||
ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { }
|
||||
void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false)
|
||||
{
|
||||
ceiling = ceil;
|
||||
getName = name;
|
||||
bitmask = mask;
|
||||
enumParams = ep;
|
||||
}
|
||||
void setOperands(OperandParameters* op) { operandParams = op; }
|
||||
int ceiling; // ceiling of enumerants
|
||||
bool bitmask; // true if these enumerants combine into a bitmask
|
||||
const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift)
|
||||
EnumParameters* enumParams; // parameters for each individual enumerant
|
||||
OperandParameters* operandParams; // sets of operands
|
||||
};
|
||||
|
||||
// Parameterize an instruction's logical format, including its known set of operands,
|
||||
// per OperandParameters above.
|
||||
class InstructionParameters {
|
||||
public:
|
||||
InstructionParameters() :
|
||||
opDesc("TBD"),
|
||||
opClass(OpClassMissing),
|
||||
typePresent(true), // most normal, only exceptions have to be spelled out
|
||||
resultPresent(true) // most normal, only exceptions have to be spelled out
|
||||
{ }
|
||||
|
||||
void setResultAndType(bool r, bool t)
|
||||
{
|
||||
resultPresent = r;
|
||||
typePresent = t;
|
||||
}
|
||||
|
||||
bool hasResult() const { return resultPresent != 0; }
|
||||
bool hasType() const { return typePresent != 0; }
|
||||
|
||||
const char* opDesc;
|
||||
OpcodeClass opClass;
|
||||
OperandParameters operands;
|
||||
|
||||
protected:
|
||||
int typePresent : 1;
|
||||
int resultPresent : 1;
|
||||
};
|
||||
|
||||
// The set of objects that hold all the instruction/operand
|
||||
// parameterization information.
|
||||
extern InstructionParameters InstructionDesc[];
|
||||
|
||||
// These hold definitions of the enumerants used for operands
|
||||
extern EnumDefinition OperandClassParams[];
|
||||
|
||||
const char* GetOperandDesc(OperandClass operand);
|
||||
void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false);
|
||||
const char* AccessQualifierString(int attr);
|
||||
|
||||
void PrintOperands(const OperandParameters& operands, int reservedOperands);
|
||||
|
||||
} // end namespace spv
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,508 @@
|
|||
//
|
||||
// Copyright (C) 2014 LunarG, Inc.
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// SPIRV-IR
|
||||
//
|
||||
// Simple in-memory representation (IR) of SPIRV. Just for holding
|
||||
// Each function's CFG of blocks. Has this hierarchy:
|
||||
// - Module, which is a list of
|
||||
// - Function, which is a list of
|
||||
// - Block, which is a list of
|
||||
// - Instruction
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef spvIR_H
|
||||
#define spvIR_H
|
||||
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace spv {
|
||||
|
||||
class Block;
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
const Id NoResult = 0;
|
||||
const Id NoType = 0;
|
||||
|
||||
const Decoration NoPrecision = DecorationMax;
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define POTENTIALLY_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define POTENTIALLY_UNUSED
|
||||
#endif
|
||||
|
||||
POTENTIALLY_UNUSED
|
||||
const MemorySemanticsMask MemorySemanticsAllMemory =
|
||||
(MemorySemanticsMask)(MemorySemanticsUniformMemoryMask |
|
||||
MemorySemanticsWorkgroupMemoryMask |
|
||||
MemorySemanticsAtomicCounterMemoryMask |
|
||||
MemorySemanticsImageMemoryMask);
|
||||
|
||||
struct IdImmediate {
|
||||
bool isId; // true if word is an Id, false if word is an immediate
|
||||
unsigned word;
|
||||
IdImmediate(bool i, unsigned w) : isId(i), word(w) {}
|
||||
};
|
||||
|
||||
//
|
||||
// SPIR-V IR instruction.
|
||||
//
|
||||
|
||||
class Instruction {
|
||||
public:
|
||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
|
||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
|
||||
virtual ~Instruction() {}
|
||||
void addIdOperand(Id id) {
|
||||
operands.push_back(id);
|
||||
idOperand.push_back(true);
|
||||
}
|
||||
void addImmediateOperand(unsigned int immediate) {
|
||||
operands.push_back(immediate);
|
||||
idOperand.push_back(false);
|
||||
}
|
||||
void setImmediateOperand(unsigned idx, unsigned int immediate) {
|
||||
assert(!idOperand[idx]);
|
||||
operands[idx] = immediate;
|
||||
}
|
||||
|
||||
void addStringOperand(const char* str)
|
||||
{
|
||||
unsigned int word;
|
||||
char* wordString = (char*)&word;
|
||||
char* wordPtr = wordString;
|
||||
int charCount = 0;
|
||||
char c;
|
||||
do {
|
||||
c = *(str++);
|
||||
*(wordPtr++) = c;
|
||||
++charCount;
|
||||
if (charCount == 4) {
|
||||
addImmediateOperand(word);
|
||||
wordPtr = wordString;
|
||||
charCount = 0;
|
||||
}
|
||||
} while (c != 0);
|
||||
|
||||
// deal with partial last word
|
||||
if (charCount > 0) {
|
||||
// pad with 0s
|
||||
for (; charCount < 4; ++charCount)
|
||||
*(wordPtr++) = 0;
|
||||
addImmediateOperand(word);
|
||||
}
|
||||
}
|
||||
bool isIdOperand(int op) const { return idOperand[op]; }
|
||||
void setBlock(Block* b) { block = b; }
|
||||
Block* getBlock() const { return block; }
|
||||
Op getOpCode() const { return opCode; }
|
||||
int getNumOperands() const
|
||||
{
|
||||
assert(operands.size() == idOperand.size());
|
||||
return (int)operands.size();
|
||||
}
|
||||
Id getResultId() const { return resultId; }
|
||||
Id getTypeId() const { return typeId; }
|
||||
Id getIdOperand(int op) const {
|
||||
assert(idOperand[op]);
|
||||
return operands[op];
|
||||
}
|
||||
unsigned int getImmediateOperand(int op) const {
|
||||
assert(!idOperand[op]);
|
||||
return operands[op];
|
||||
}
|
||||
|
||||
// Write out the binary form.
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// Compute the wordCount
|
||||
unsigned int wordCount = 1;
|
||||
if (typeId)
|
||||
++wordCount;
|
||||
if (resultId)
|
||||
++wordCount;
|
||||
wordCount += (unsigned int)operands.size();
|
||||
|
||||
// Write out the beginning of the instruction
|
||||
out.push_back(((wordCount) << WordCountShift) | opCode);
|
||||
if (typeId)
|
||||
out.push_back(typeId);
|
||||
if (resultId)
|
||||
out.push_back(resultId);
|
||||
|
||||
// Write out the operands
|
||||
for (int op = 0; op < (int)operands.size(); ++op)
|
||||
out.push_back(operands[op]);
|
||||
}
|
||||
|
||||
protected:
|
||||
Instruction(const Instruction&);
|
||||
Id resultId;
|
||||
Id typeId;
|
||||
Op opCode;
|
||||
std::vector<Id> operands; // operands, both <id> and immediates (both are unsigned int)
|
||||
std::vector<bool> idOperand; // true for operands that are <id>, false for immediates
|
||||
Block* block;
|
||||
};
|
||||
|
||||
//
|
||||
// SPIR-V IR block.
|
||||
//
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block(Id id, Function& parent);
|
||||
virtual ~Block()
|
||||
{
|
||||
}
|
||||
|
||||
Id getId() { return instructions.front()->getResultId(); }
|
||||
|
||||
Function& getParent() const { return parent; }
|
||||
void addInstruction(std::unique_ptr<Instruction> inst);
|
||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
|
||||
const std::vector<Block*>& getPredecessors() const { return predecessors; }
|
||||
const std::vector<Block*>& getSuccessors() const { return successors; }
|
||||
const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
|
||||
return instructions;
|
||||
}
|
||||
const std::vector<std::unique_ptr<Instruction> >& getLocalVariables() const { return localVariables; }
|
||||
void setUnreachable() { unreachable = true; }
|
||||
bool isUnreachable() const { return unreachable; }
|
||||
// Returns the block's merge instruction, if one exists (otherwise null).
|
||||
const Instruction* getMergeInstruction() const {
|
||||
if (instructions.size() < 2) return nullptr;
|
||||
const Instruction* nextToLast = (instructions.cend() - 2)->get();
|
||||
switch (nextToLast->getOpCode()) {
|
||||
case OpSelectionMerge:
|
||||
case OpLoopMerge:
|
||||
return nextToLast;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Change this block into a canonical dead merge block. Delete instructions
|
||||
// as necessary. A canonical dead merge block has only an OpLabel and an
|
||||
// OpUnreachable.
|
||||
void rewriteAsCanonicalUnreachableMerge() {
|
||||
assert(localVariables.empty());
|
||||
// Delete all instructions except for the label.
|
||||
assert(instructions.size() > 0);
|
||||
instructions.resize(1);
|
||||
successors.clear();
|
||||
addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
|
||||
}
|
||||
// Change this block into a canonical dead continue target branching to the
|
||||
// given header ID. Delete instructions as necessary. A canonical dead continue
|
||||
// target has only an OpLabel and an unconditional branch back to the corresponding
|
||||
// header.
|
||||
void rewriteAsCanonicalUnreachableContinue(Block* header) {
|
||||
assert(localVariables.empty());
|
||||
// Delete all instructions except for the label.
|
||||
assert(instructions.size() > 0);
|
||||
instructions.resize(1);
|
||||
successors.clear();
|
||||
// Add OpBranch back to the header.
|
||||
assert(header != nullptr);
|
||||
Instruction* branch = new Instruction(OpBranch);
|
||||
branch->addIdOperand(header->getId());
|
||||
addInstruction(std::unique_ptr<Instruction>(branch));
|
||||
successors.push_back(header);
|
||||
}
|
||||
|
||||
bool isTerminated() const
|
||||
{
|
||||
switch (instructions.back()->getOpCode()) {
|
||||
case OpBranch:
|
||||
case OpBranchConditional:
|
||||
case OpSwitch:
|
||||
case OpKill:
|
||||
case OpTerminateInvocation:
|
||||
case OpReturn:
|
||||
case OpReturnValue:
|
||||
case OpUnreachable:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
instructions[0]->dump(out);
|
||||
for (int i = 0; i < (int)localVariables.size(); ++i)
|
||||
localVariables[i]->dump(out);
|
||||
for (int i = 1; i < (int)instructions.size(); ++i)
|
||||
instructions[i]->dump(out);
|
||||
}
|
||||
|
||||
protected:
|
||||
Block(const Block&);
|
||||
Block& operator=(Block&);
|
||||
|
||||
// To enforce keeping parent and ownership in sync:
|
||||
friend Function;
|
||||
|
||||
std::vector<std::unique_ptr<Instruction> > instructions;
|
||||
std::vector<Block*> predecessors, successors;
|
||||
std::vector<std::unique_ptr<Instruction> > localVariables;
|
||||
Function& parent;
|
||||
|
||||
// track whether this block is known to be uncreachable (not necessarily
|
||||
// true for all unreachable blocks, but should be set at least
|
||||
// for the extraneous ones introduced by the builder).
|
||||
bool unreachable;
|
||||
};
|
||||
|
||||
// The different reasons for reaching a block in the inReadableOrder traversal.
|
||||
enum ReachReason {
|
||||
// Reachable from the entry block via transfers of control, i.e. branches.
|
||||
ReachViaControlFlow = 0,
|
||||
// A continue target that is not reachable via control flow.
|
||||
ReachDeadContinue,
|
||||
// A merge block that is not reachable via control flow.
|
||||
ReachDeadMerge
|
||||
};
|
||||
|
||||
// Traverses the control-flow graph rooted at root in an order suited for
|
||||
// readable code generation. Invokes callback at every node in the traversal
|
||||
// order. The callback arguments are:
|
||||
// - the block,
|
||||
// - the reason we reached the block,
|
||||
// - if the reason was that block is an unreachable continue or unreachable merge block
|
||||
// then the last parameter is the corresponding header block.
|
||||
void inReadableOrder(Block* root, std::function<void(Block*, ReachReason, Block* header)> callback);
|
||||
|
||||
//
|
||||
// SPIR-V IR Function.
|
||||
//
|
||||
|
||||
class Function {
|
||||
public:
|
||||
Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent);
|
||||
virtual ~Function()
|
||||
{
|
||||
for (int i = 0; i < (int)parameterInstructions.size(); ++i)
|
||||
delete parameterInstructions[i];
|
||||
|
||||
for (int i = 0; i < (int)blocks.size(); ++i)
|
||||
delete blocks[i];
|
||||
}
|
||||
Id getId() const { return functionInstruction.getResultId(); }
|
||||
Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); }
|
||||
Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); }
|
||||
|
||||
void addBlock(Block* block) { blocks.push_back(block); }
|
||||
void removeBlock(Block* block)
|
||||
{
|
||||
auto found = find(blocks.begin(), blocks.end(), block);
|
||||
assert(found != blocks.end());
|
||||
blocks.erase(found);
|
||||
delete block;
|
||||
}
|
||||
|
||||
Module& getParent() const { return parent; }
|
||||
Block* getEntryBlock() const { return blocks.front(); }
|
||||
Block* getLastBlock() const { return blocks.back(); }
|
||||
const std::vector<Block*>& getBlocks() const { return blocks; }
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst);
|
||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||
void setReturnPrecision(Decoration precision)
|
||||
{
|
||||
if (precision == DecorationRelaxedPrecision)
|
||||
reducedPrecisionReturn = true;
|
||||
}
|
||||
Decoration getReturnPrecision() const
|
||||
{ return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
|
||||
|
||||
void setImplicitThis() { implicitThis = true; }
|
||||
bool hasImplicitThis() const { return implicitThis; }
|
||||
|
||||
void addParamPrecision(unsigned param, Decoration precision)
|
||||
{
|
||||
if (precision == DecorationRelaxedPrecision)
|
||||
reducedPrecisionParams.insert(param);
|
||||
}
|
||||
Decoration getParamPrecision(unsigned param) const
|
||||
{
|
||||
return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ?
|
||||
DecorationRelaxedPrecision : NoPrecision;
|
||||
}
|
||||
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// OpFunction
|
||||
functionInstruction.dump(out);
|
||||
|
||||
// OpFunctionParameter
|
||||
for (int p = 0; p < (int)parameterInstructions.size(); ++p)
|
||||
parameterInstructions[p]->dump(out);
|
||||
|
||||
// Blocks
|
||||
inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); });
|
||||
Instruction end(0, 0, OpFunctionEnd);
|
||||
end.dump(out);
|
||||
}
|
||||
|
||||
protected:
|
||||
Function(const Function&);
|
||||
Function& operator=(Function&);
|
||||
|
||||
Module& parent;
|
||||
Instruction functionInstruction;
|
||||
std::vector<Instruction*> parameterInstructions;
|
||||
std::vector<Block*> blocks;
|
||||
bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
|
||||
bool reducedPrecisionReturn;
|
||||
std::set<int> reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg
|
||||
};
|
||||
|
||||
//
|
||||
// SPIR-V IR Module.
|
||||
//
|
||||
|
||||
class Module {
|
||||
public:
|
||||
Module() {}
|
||||
virtual ~Module()
|
||||
{
|
||||
// TODO delete things
|
||||
}
|
||||
|
||||
void addFunction(Function *fun) { functions.push_back(fun); }
|
||||
|
||||
void mapInstruction(Instruction *instruction)
|
||||
{
|
||||
spv::Id resultId = instruction->getResultId();
|
||||
// map the instruction's result id
|
||||
if (resultId >= idToInstruction.size())
|
||||
idToInstruction.resize(resultId + 16);
|
||||
idToInstruction[resultId] = instruction;
|
||||
}
|
||||
|
||||
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
|
||||
const std::vector<Function*>& getFunctions() const { return functions; }
|
||||
spv::Id getTypeId(Id resultId) const {
|
||||
return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId();
|
||||
}
|
||||
StorageClass getStorageClass(Id typeId) const
|
||||
{
|
||||
assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer);
|
||||
return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0);
|
||||
}
|
||||
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
for (int f = 0; f < (int)functions.size(); ++f)
|
||||
functions[f]->dump(out);
|
||||
}
|
||||
|
||||
protected:
|
||||
Module(const Module&);
|
||||
std::vector<Function*> functions;
|
||||
|
||||
// map from result id to instruction having that result id
|
||||
std::vector<Instruction*> idToInstruction;
|
||||
|
||||
// map from a result id to its type id
|
||||
};
|
||||
|
||||
//
|
||||
// Implementation (it's here due to circular type definitions).
|
||||
//
|
||||
|
||||
// Add both
|
||||
// - the OpFunction instruction
|
||||
// - all the OpFunctionParameter instructions
|
||||
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
|
||||
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false),
|
||||
reducedPrecisionReturn(false)
|
||||
{
|
||||
// OpFunction
|
||||
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
||||
functionInstruction.addIdOperand(functionType);
|
||||
parent.mapInstruction(&functionInstruction);
|
||||
parent.addFunction(this);
|
||||
|
||||
// OpFunctionParameter
|
||||
Instruction* typeInst = parent.getInstruction(functionType);
|
||||
int numParams = typeInst->getNumOperands() - 1;
|
||||
for (int p = 0; p < numParams; ++p) {
|
||||
Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter);
|
||||
parent.mapInstruction(param);
|
||||
parameterInstructions.push_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
__inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst)
|
||||
{
|
||||
Instruction* raw_instruction = inst.get();
|
||||
blocks[0]->addLocalVariable(std::move(inst));
|
||||
parent.mapInstruction(raw_instruction);
|
||||
}
|
||||
|
||||
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
|
||||
{
|
||||
instructions.push_back(std::unique_ptr<Instruction>(new Instruction(id, NoType, OpLabel)));
|
||||
instructions.back()->setBlock(this);
|
||||
parent.getParent().mapInstruction(instructions.back().get());
|
||||
}
|
||||
|
||||
__inline void Block::addInstruction(std::unique_ptr<Instruction> inst)
|
||||
{
|
||||
Instruction* raw_instruction = inst.get();
|
||||
instructions.push_back(std::move(inst));
|
||||
raw_instruction->setBlock(this);
|
||||
if (raw_instruction->getResultId())
|
||||
parent.getParent().mapInstruction(raw_instruction);
|
||||
}
|
||||
|
||||
} // end spv namespace
|
||||
|
||||
#endif // spvIR_H
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (C) 2020 The Khronos Group Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of The Khronos Group Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GLSLANG_BUILD_INFO
|
||||
#define GLSLANG_BUILD_INFO
|
||||
|
||||
#define GLSLANG_VERSION_MAJOR 11
|
||||
#define GLSLANG_VERSION_MINOR 4
|
||||
#define GLSLANG_VERSION_PATCH 0
|
||||
#define GLSLANG_VERSION_FLAVOR ""
|
||||
|
||||
#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \
|
||||
(((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
|
||||
(((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
|
||||
((patch) > GLSLANG_VERSION_PATCH)))))
|
||||
|
||||
#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \
|
||||
(((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
|
||||
(((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
|
||||
((patch) >= GLSLANG_VERSION_PATCH)))))
|
||||
|
||||
#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \
|
||||
(((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
|
||||
(((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
|
||||
((patch) < GLSLANG_VERSION_PATCH)))))
|
||||
|
||||
#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \
|
||||
(((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
|
||||
(((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
|
||||
((patch) <= GLSLANG_VERSION_PATCH)))))
|
||||
|
||||
#endif // GLSLANG_BUILD_INFO
|
||||
|
|
@ -85,7 +85,7 @@ WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
|
|||
// Upon return, the Y buffer has a stride returned as '*stride', while U and V
|
||||
// have a common stride returned as '*uv_stride'.
|
||||
// Return NULL in case of error.
|
||||
// (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr
|
||||
// (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr
|
||||
WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
|
||||
int* width, int* height,
|
||||
uint8_t** u, uint8_t** v,
|
||||
|
|
|
|||
|
|
@ -1,38 +1,8 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup lejp JSON parser
|
||||
* ##JSON parsing related functions
|
||||
* \ingroup lwsapi
|
||||
*
|
||||
* LEJP is an extremely lightweight JSON stream parser included in lws.
|
||||
*/
|
||||
//@{
|
||||
#include "libwebsockets.h"
|
||||
struct lejp_ctx;
|
||||
|
||||
#if !defined(LWS_ARRAY_SIZE)
|
||||
#define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
|
||||
#endif
|
||||
#define LEJP_FLAG_WS_KEEP 64
|
||||
#define LEJP_FLAG_WS_COMMENTLINE 32
|
||||
|
|
@ -107,7 +77,7 @@ enum lejp_callbacks {
|
|||
LEJPCB_ARRAY_END = 15,
|
||||
|
||||
LEJPCB_OBJECT_START = 16,
|
||||
LEJPCB_OBJECT_END = 17,
|
||||
LEJPCB_OBJECT_END = 17
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -153,12 +123,11 @@ enum lejp_callbacks {
|
|||
*
|
||||
* LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet
|
||||
*
|
||||
* LEJPCB_VAL_STR_CHUNK: We filled the string buffer in the ctx, but it's not
|
||||
* the end of the string. We produce this to spill the
|
||||
* intermediate buffer to the user code, so we can handle
|
||||
* huge JSON strings using only the small buffer in the
|
||||
* ctx. If the whole JSON string fits in the ctx buffer,
|
||||
* you won't get these callbacks.
|
||||
* LEJPCB_VAL_STR_CHUNK: We parsed LEJP_STRING_CHUNK -1 bytes of string data in
|
||||
* ctx->buf, which is as much as we can buffer, so we are
|
||||
* spilling it. If all your strings are less than
|
||||
* LEJP_STRING_CHUNK - 1 bytes, you will never see this
|
||||
* callback.
|
||||
*
|
||||
* LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the
|
||||
* string is in ctx->buf.
|
||||
|
|
@ -175,44 +144,32 @@ LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason);
|
|||
|
||||
typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
|
||||
|
||||
#ifndef LEJP_MAX_PARSING_STACK_DEPTH
|
||||
#define LEJP_MAX_PARSING_STACK_DEPTH 5
|
||||
#endif
|
||||
#ifndef LEJP_MAX_DEPTH
|
||||
#define LEJP_MAX_DEPTH 12
|
||||
#endif
|
||||
#ifndef LEJP_MAX_INDEX_DEPTH
|
||||
#define LEJP_MAX_INDEX_DEPTH 8
|
||||
#define LEJP_MAX_INDEX_DEPTH 5
|
||||
#endif
|
||||
#ifndef LEJP_MAX_PATH
|
||||
#define LEJP_MAX_PATH 128
|
||||
#endif
|
||||
#ifndef LEJP_STRING_CHUNK
|
||||
/* must be >= 30 to assemble floats */
|
||||
#define LEJP_STRING_CHUNK 254
|
||||
#define LEJP_STRING_CHUNK 255
|
||||
#endif
|
||||
|
||||
enum num_flags {
|
||||
LEJP_SEEN_MINUS = (1 << 0),
|
||||
LEJP_SEEN_POINT = (1 << 1),
|
||||
LEJP_SEEN_POST_POINT = (1 << 2),
|
||||
LEJP_SEEN_EXP = (1 << 3)
|
||||
LEJP_SEEN_MINUS = (1 << 0),
|
||||
LEJP_SEEN_POINT = (1 << 1),
|
||||
LEJP_SEEN_POST_POINT = (1 << 2),
|
||||
LEJP_SEEN_EXP = (1 << 3)
|
||||
};
|
||||
|
||||
struct _lejp_stack {
|
||||
char s; /* lejp_state stack*/
|
||||
char p; /* path length */
|
||||
char i; /* index array length */
|
||||
char b; /* user bitfield */
|
||||
};
|
||||
|
||||
struct _lejp_parsing_stack {
|
||||
void *user; /* private to the stack level */
|
||||
signed char (*callback)(struct lejp_ctx *ctx, char reason);
|
||||
const char * const *paths;
|
||||
uint8_t count_paths;
|
||||
uint8_t ppos;
|
||||
uint8_t path_match;
|
||||
char s; /* lejp_state stack*/
|
||||
char p; /* path length */
|
||||
char i; /* index array length */
|
||||
char b; /* user bitfield */
|
||||
};
|
||||
|
||||
struct lejp_ctx {
|
||||
|
|
@ -221,42 +178,39 @@ struct lejp_ctx {
|
|||
*
|
||||
* pointers
|
||||
*/
|
||||
|
||||
signed char (*callback)(struct lejp_ctx *ctx, char reason);
|
||||
void *user;
|
||||
const char * const *paths;
|
||||
|
||||
/* arrays */
|
||||
|
||||
struct _lejp_parsing_stack pst[LEJP_MAX_PARSING_STACK_DEPTH];
|
||||
struct _lejp_stack st[LEJP_MAX_DEPTH];
|
||||
uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
unsigned short i[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
unsigned short wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
|
||||
char path[LEJP_MAX_PATH];
|
||||
char buf[LEJP_STRING_CHUNK + 1];
|
||||
|
||||
/* size_t */
|
||||
|
||||
size_t path_stride; /* 0 means default ptr size, else stride */
|
||||
char buf[LEJP_STRING_CHUNK];
|
||||
|
||||
/* int */
|
||||
|
||||
uint32_t line;
|
||||
unsigned int line;
|
||||
|
||||
/* short */
|
||||
|
||||
uint16_t uni;
|
||||
unsigned short uni;
|
||||
|
||||
/* char */
|
||||
|
||||
uint8_t npos;
|
||||
uint8_t dcount;
|
||||
uint8_t f;
|
||||
uint8_t sp; /* stack head */
|
||||
uint8_t ipos; /* index stack depth */
|
||||
uint8_t count_paths;
|
||||
uint8_t path_match;
|
||||
uint8_t path_match_len;
|
||||
uint8_t wildcount;
|
||||
uint8_t pst_sp; /* parsing stack head */
|
||||
uint8_t outer_array;
|
||||
unsigned char npos;
|
||||
unsigned char dcount;
|
||||
unsigned char f;
|
||||
unsigned char sp; /* stack head */
|
||||
unsigned char ipos; /* index stack depth */
|
||||
unsigned char ppos;
|
||||
unsigned char count_paths;
|
||||
unsigned char path_match;
|
||||
unsigned char path_match_len;
|
||||
unsigned char wildcount;
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
|
|
@ -274,28 +228,5 @@ LWS_VISIBLE LWS_EXTERN void
|
|||
lejp_change_callback(struct lejp_ctx *ctx,
|
||||
signed char (*callback)(struct lejp_ctx *ctx, char reason));
|
||||
|
||||
/*
|
||||
* push the current paths / paths_count and lejp_cb to a stack in the ctx, and
|
||||
* start using the new ones
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lejp_parser_push(struct lejp_ctx *ctx, void *user, const char * const *paths,
|
||||
unsigned char paths_count, lejp_callback lejp_cb);
|
||||
|
||||
/*
|
||||
* pop the previously used paths / paths_count and lejp_cb, and continue
|
||||
* parsing using those as before
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lejp_parser_pop(struct lejp_ctx *ctx);
|
||||
|
||||
/* exported for use when reevaluating a path for use with a subcontext */
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lejp_check_path_match(struct lejp_ctx *ctx);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const char *
|
||||
lejp_error_to_string(int e);
|
||||
//@}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These are used to optionally pass an array of index = C string, binary array,
|
||||
* or ulong tokens to the abstract transport or protocol. For example if it's
|
||||
* raw socket transport, then the DNS address to connect to and the port are
|
||||
* passed using these when the client created and bound to the transport.
|
||||
*/
|
||||
|
||||
typedef struct lws_token_map {
|
||||
union {
|
||||
const char *value;
|
||||
uint8_t *bvalue;
|
||||
unsigned long lvalue;
|
||||
} u;
|
||||
short name_index; /* 0 here indicates end of array */
|
||||
short length_or_zero;
|
||||
} lws_token_map_t;
|
||||
|
||||
/*
|
||||
* The indvidual protocols and transports define their own name_index-es which
|
||||
* are meaningful to them. Define index 0 globally as the end of an array of
|
||||
* them, and provide bases so user protocol and transport ones don't overlap.
|
||||
*/
|
||||
|
||||
enum {
|
||||
LTMI_END_OF_ARRAY,
|
||||
|
||||
LTMI_PROTOCOL_BASE = 2048,
|
||||
|
||||
LTMI_TRANSPORT_BASE = 4096
|
||||
};
|
||||
|
||||
struct lws_abs_transport;
|
||||
struct lws_abs_protocol;
|
||||
typedef struct lws_abs lws_abs_t;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const lws_token_map_t *
|
||||
lws_abs_get_token(const lws_token_map_t *token_map, short name_index);
|
||||
|
||||
/*
|
||||
* the combination of a protocol, transport, and token maps for each
|
||||
*/
|
||||
|
||||
typedef void lws_abs_transport_inst_t;
|
||||
typedef void lws_abs_protocol_inst_t;
|
||||
|
||||
/**
|
||||
* lws_abstract_alloc() - allocate and configure an lws_abs_t
|
||||
*
|
||||
* \param vhost: the struct lws_vhost to bind to
|
||||
* \param user: opaque user pointer
|
||||
* \param abstract_path: "protocol.transport" names
|
||||
* \param ap_tokens: tokens for protocol options
|
||||
* \param at_tokens: tokens for transport
|
||||
* \param seq: optional sequencer we should bind to, or NULL
|
||||
* \param opaque_user_data: data given in sequencer callback, if any
|
||||
*
|
||||
* Returns an allocated lws_abs_t pointer set up with the other arguments.
|
||||
*
|
||||
* Doesn't create a connection instance, just allocates the lws_abs_t and
|
||||
* sets it up with the arguments.
|
||||
*
|
||||
* Returns NULL is there's any problem.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN lws_abs_t *
|
||||
lws_abstract_alloc(struct lws_vhost *vhost, void *user,
|
||||
const char *abstract_path, const lws_token_map_t *ap_tokens,
|
||||
const lws_token_map_t *at_tokens, struct lws_sequencer *seq,
|
||||
void *opaque_user_data);
|
||||
|
||||
/**
|
||||
* lws_abstract_free() - free an allocated lws_abs_t
|
||||
*
|
||||
* \param pabs: pointer to the lws_abs_t * to free
|
||||
*
|
||||
* Frees and sets the pointer to NULL.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_abstract_free(lws_abs_t **pabs);
|
||||
|
||||
/**
|
||||
* lws_abs_bind_and_create_instance - use an abstract protocol and transport
|
||||
*
|
||||
* \param abs: the lws_abs_t describing the combination desired
|
||||
*
|
||||
* This instantiates an abstract protocol and abstract transport bound together.
|
||||
* A single heap allocation is made for the combination and the protocol and
|
||||
* transport creation ops are called on it. The ap_tokens and at_tokens
|
||||
* are consulted by the creation ops to decide the details of the protocol and
|
||||
* transport for the instance.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN lws_abs_t *
|
||||
lws_abs_bind_and_create_instance(const lws_abs_t *ai);
|
||||
|
||||
/**
|
||||
* lws_abs_destroy_instance() - destroys an instance
|
||||
*
|
||||
* \param ai: pointer to the ai pointer to destroy
|
||||
*
|
||||
* This is for destroying an instance created by
|
||||
* lws_abs_bind_and_create_instance() above.
|
||||
*
|
||||
* Calls the protocol and transport destroy operations on the instance, then
|
||||
* frees the combined allocation in one step. The pointer ai is set to NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_abs_destroy_instance(lws_abs_t **ai);
|
||||
|
||||
/*
|
||||
* bring in all the protocols and transports definitions
|
||||
*/
|
||||
|
||||
#include <libwebsockets/abstract/protocols.h>
|
||||
#include <libwebsockets/abstract/transports.h>
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Information about how this protocol handles multiple use of connections.
|
||||
*
|
||||
* .flags of 0 indicates each connection must start with a fresh transport.
|
||||
*
|
||||
* Flags can be used to indicate the protocol itself supports different
|
||||
* kinds of multiple use. However the actual use or not of these may depend on
|
||||
* negotiation with the remote peer.
|
||||
*
|
||||
* LWS_AP_FLAG_PIPELINE_TRANSACTIONS: other instances can be queued on one
|
||||
* with an existing connection and get a
|
||||
* chance to "hot take over" the existing
|
||||
* transport in turn, like h1 keepalive
|
||||
* pipelining
|
||||
*
|
||||
* LWS_AP_FLAG_MUXABLE_STREAM: an existing connection can absorb more child
|
||||
* connections and mux them as separate child
|
||||
* streams ongoing, like h2
|
||||
*/
|
||||
|
||||
enum {
|
||||
LWS_AP_FLAG_PIPELINE_TRANSACTIONS = (1 << 0),
|
||||
LWS_AP_FLAG_MUXABLE_STREAM = (1 << 1),
|
||||
};
|
||||
|
||||
typedef struct lws_abs_protocol {
|
||||
const char *name;
|
||||
int alloc;
|
||||
int flags;
|
||||
|
||||
int (*create)(const struct lws_abs *ai);
|
||||
void (*destroy)(lws_abs_protocol_inst_t **d);
|
||||
int (*compare)(lws_abs_t *abs1, lws_abs_t *abs2);
|
||||
|
||||
/* events the transport invokes (handled by abstract protocol) */
|
||||
|
||||
int (*accept)(lws_abs_protocol_inst_t *d);
|
||||
int (*rx)(lws_abs_protocol_inst_t *d, const uint8_t *b, size_t l);
|
||||
int (*writeable)(lws_abs_protocol_inst_t *d, size_t budget);
|
||||
int (*closed)(lws_abs_protocol_inst_t *d);
|
||||
int (*heartbeat)(lws_abs_protocol_inst_t *d);
|
||||
|
||||
/* as parent, we get a notification a new child / queue entry
|
||||
* bound to us... this is the parent lws_abs_t as arg */
|
||||
int (*child_bind)(lws_abs_t *abs);
|
||||
} lws_abs_protocol_t;
|
||||
|
||||
/**
|
||||
* lws_abs_protocol_get_by_name() - returns a pointer to the named protocol ops
|
||||
*
|
||||
* \param name: the name of the abstract protocol
|
||||
*
|
||||
* Returns a pointer to the named protocol ops struct if available, otherwise
|
||||
* NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN const lws_abs_protocol_t *
|
||||
lws_abs_protocol_get_by_name(const char *name);
|
||||
|
||||
/*
|
||||
* bring in public api pieces from protocols
|
||||
*/
|
||||
|
||||
#include <libwebsockets/abstract/protocols/smtp.h>
|
||||
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup smtp SMTP related functions
|
||||
* ##SMTP related functions
|
||||
* \ingroup lwsapi
|
||||
*
|
||||
* These apis let you communicate with a local SMTP server to send email from
|
||||
* lws. It handles all the SMTP sequencing and protocol actions.
|
||||
*
|
||||
* Your system should have postfix, sendmail or another MTA listening on port
|
||||
* 25 and able to send email using the "mail" commandline app. Usually distro
|
||||
* MTAs are configured for this by default.
|
||||
*
|
||||
* You can either use the abstract protocol layer directly, or instead use the
|
||||
* provided smtp sequencer... this takes care of creating the protocol
|
||||
* connections, and provides and email queue and retry management.
|
||||
*/
|
||||
//@{
|
||||
|
||||
#if defined(LWS_WITH_SMTP)
|
||||
|
||||
enum {
|
||||
LTMI_PSMTP_V_HELO = LTMI_PROTOCOL_BASE, /* u.value */
|
||||
|
||||
LTMI_PSMTP_V_LWS_SMTP_EMAIL_T, /* u.value */
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_SMTP_DISPOSITION_SENT,
|
||||
LWS_SMTP_DISPOSITION_FAILED,
|
||||
LWS_SMTP_DISPOSITION_FAILED_DESTROY
|
||||
};
|
||||
|
||||
typedef struct lws_smtp_sequencer_args {
|
||||
const char helo[32];
|
||||
struct lws_vhost *vhost;
|
||||
time_t retry_interval;
|
||||
time_t delivery_timeout;
|
||||
size_t email_queue_max;
|
||||
size_t max_content_size;
|
||||
} lws_smtp_sequencer_args_t;
|
||||
|
||||
typedef struct lws_smtp_sequencer lws_smtp_sequencer_t;
|
||||
typedef struct lws_smtp_email lws_smtp_email_t;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN lws_smtp_sequencer_t *
|
||||
lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t *args);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_smtp_sequencer_destroy(lws_smtp_sequencer_t *s);
|
||||
|
||||
typedef int (*lws_smtp_cb_t)(void *e, void *d, int disp, const void *b, size_t l);
|
||||
typedef struct lws_smtp_email lws_smtp_email_t;
|
||||
|
||||
/**
|
||||
* lws_smtpc_add_email() - Allocates and queues an email object
|
||||
*
|
||||
* \param s: smtp sequencer to queue on
|
||||
* \param payload: the email payload string, with headers and terminating .
|
||||
* \param payload_len: size in bytes of the payload string
|
||||
* \param sender: the sender name and email
|
||||
* \param recipient: the recipient name and email
|
||||
* \param data: opaque user data returned in the done callback
|
||||
* \param done: callback called when the email send succeeded or failed
|
||||
*
|
||||
* Allocates an email object and copies the payload, sender and recipient into
|
||||
* it and initializes it. Returns NULL if OOM, otherwise the allocated email
|
||||
* object.
|
||||
*
|
||||
* Because it copies the arguments into an allocated buffer, the original
|
||||
* arguments can be safely destroyed after calling this.
|
||||
*
|
||||
* The done() callback must free the email object. It doesn't have to free any
|
||||
* individual members.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_smtpc_add_email(lws_smtp_sequencer_t *s, const char *payload,
|
||||
size_t payload_len, const char *sender,
|
||||
const char *recipient, void *data, lws_smtp_cb_t done);
|
||||
|
||||
/**
|
||||
* lws_smtpc_free_email() - Add email to the list of ones being sent
|
||||
*
|
||||
* \param e: email to queue for sending on \p c
|
||||
*
|
||||
* Adds an email to the linked-list of emails to send
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_smtpc_free_email(lws_smtp_email_t *e);
|
||||
|
||||
|
||||
#endif
|
||||
//@}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abstract transport ops
|
||||
*/
|
||||
|
||||
typedef struct lws_abs_transport {
|
||||
const char *name;
|
||||
int alloc;
|
||||
|
||||
int (*create)(lws_abs_t *abs);
|
||||
void (*destroy)(lws_abs_transport_inst_t **d);
|
||||
|
||||
/* check if the transport settings for these connections are the same */
|
||||
int (*compare)(lws_abs_t *abs1, lws_abs_t *abs2);
|
||||
|
||||
/* events the abstract protocol invokes (handled by transport) */
|
||||
|
||||
int (*tx)(lws_abs_transport_inst_t *d, uint8_t *buf, size_t len);
|
||||
int (*client_conn)(const lws_abs_t *abs);
|
||||
int (*close)(lws_abs_transport_inst_t *d);
|
||||
int (*ask_for_writeable)(lws_abs_transport_inst_t *d);
|
||||
int (*set_timeout)(lws_abs_transport_inst_t *d, int reason, int secs);
|
||||
int (*state)(lws_abs_transport_inst_t *d);
|
||||
} lws_abs_transport_t;
|
||||
|
||||
/**
|
||||
* lws_abs_protocol_get_by_name() - returns a pointer to the named protocol ops
|
||||
*
|
||||
* \param name: the name of the abstract protocol
|
||||
*
|
||||
* Returns a pointer to the named protocol ops struct if available, otherwise
|
||||
* NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN const lws_abs_transport_t *
|
||||
lws_abs_transport_get_by_name(const char *name);
|
||||
|
||||
/*
|
||||
* bring in public api pieces from transports
|
||||
*/
|
||||
|
||||
#include <libwebsockets/abstract/transports/raw-skt.h>
|
||||
#include <libwebsockets/abstract/transports/unit-test.h>
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
enum {
|
||||
LTMI_PEER_V_DNS_ADDRESS = LTMI_TRANSPORT_BASE, /* u.value */
|
||||
LTMI_PEER_LV_PORT, /* u.lvalue */
|
||||
LTMI_PEER_LV_TLS_FLAGS, /* u.lvalue */
|
||||
};
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is an abstract transport useful for unit testing abstract protocols.
|
||||
*
|
||||
* Instead of passing data anywhere, you give the transport a list of packets
|
||||
* to deliver and packets you expect back from the abstract protocol it's
|
||||
* bound to.
|
||||
*/
|
||||
|
||||
enum {
|
||||
LWS_AUT_EXPECT_TEST_END = (1 << 0),
|
||||
LWS_AUT_EXPECT_LOCAL_CLOSE = (1 << 1),
|
||||
LWS_AUT_EXPECT_DO_REMOTE_CLOSE = (1 << 2),
|
||||
LWS_AUT_EXPECT_TX /* expect this as tx from protocol */ = (1 << 3),
|
||||
LWS_AUT_EXPECT_RX /* present this as rx to protocol */ = (1 << 4),
|
||||
LWS_AUT_EXPECT_SHOULD_FAIL = (1 << 5),
|
||||
LWS_AUT_EXPECT_SHOULD_TIMEOUT = (1 << 6),
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LPE_CONTINUE,
|
||||
LPE_SUCCEEDED,
|
||||
LPE_FAILED,
|
||||
LPE_FAILED_UNEXPECTED_TIMEOUT,
|
||||
LPE_FAILED_UNEXPECTED_PASS,
|
||||
LPE_FAILED_UNEXPECTED_CLOSE,
|
||||
LPE_SKIPPED,
|
||||
LPE_CLOSING
|
||||
} lws_unit_test_packet_disposition;
|
||||
|
||||
typedef int (*lws_unit_test_packet_test_cb)(const void *cb_user, int disposition);
|
||||
typedef int (*lws_unit_test_packet_cb)(lws_abs_t *instance);
|
||||
|
||||
/* each step in the unit test */
|
||||
|
||||
typedef struct lws_unit_test_packet {
|
||||
void *buffer;
|
||||
lws_unit_test_packet_cb pre;
|
||||
size_t len;
|
||||
|
||||
uint32_t flags;
|
||||
} lws_unit_test_packet_t;
|
||||
|
||||
/* each unit test */
|
||||
|
||||
typedef struct lws_unit_test {
|
||||
const char * name; /* NULL indicates end of test array */
|
||||
lws_unit_test_packet_t * expect_array;
|
||||
int max_secs;
|
||||
} lws_unit_test_t;
|
||||
|
||||
enum {
|
||||
LTMI_PEER_V_EXPECT_TEST = LTMI_TRANSPORT_BASE, /* u.value */
|
||||
LTMI_PEER_V_EXPECT_RESULT_CB, /* u.value */
|
||||
LTMI_PEER_V_EXPECT_RESULT_CB_ARG, /* u.value */
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const char *
|
||||
lws_unit_test_result_name(int in);
|
||||
|
||||
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup sock-adopt Socket adoption helpers
|
||||
* ##Socket adoption helpers
|
||||
*
|
||||
* When integrating with an external app with its own event loop, these can
|
||||
* be used to accept connections from someone else's listening socket.
|
||||
*
|
||||
* When using lws own event loop, these are not needed.
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* lws_adopt_socket() - adopt foreign socket as if listen socket accepted it
|
||||
* for the default vhost of context.
|
||||
*
|
||||
* \param context: lws context
|
||||
* \param accept_fd: fd of already-accepted socket to adopt
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
*
|
||||
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
|
||||
* to ws or just serve http.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd);
|
||||
/**
|
||||
* lws_adopt_socket_vhost() - adopt foreign socket as if listen socket accepted
|
||||
* it for vhost
|
||||
*
|
||||
* \param vh: lws vhost
|
||||
* \param accept_fd: fd of already-accepted socket to adopt
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
*
|
||||
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
|
||||
* to ws or just serve http.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
|
||||
|
||||
typedef enum {
|
||||
LWS_ADOPT_RAW_FILE_DESC = 0, /* convenience constant */
|
||||
LWS_ADOPT_HTTP = 1, /* flag: absent implies RAW */
|
||||
LWS_ADOPT_SOCKET = 2, /* flag: absent implies file */
|
||||
LWS_ADOPT_ALLOW_SSL = 4, /* flag: use tls */
|
||||
LWS_ADOPT_FLAG_UDP = 16, /* flag: socket is UDP */
|
||||
LWS_ADOPT_FLAG_RAW_PROXY = 32, /* flag: raw proxy */
|
||||
|
||||
LWS_ADOPT_RAW_SOCKET_UDP = LWS_ADOPT_SOCKET | LWS_ADOPT_FLAG_UDP,
|
||||
} lws_adoption_type;
|
||||
|
||||
typedef union {
|
||||
lws_sockfd_type sockfd;
|
||||
lws_filefd_type filefd;
|
||||
} lws_sock_file_fd_type;
|
||||
|
||||
#if defined(LWS_ESP_PLATFORM)
|
||||
#include <lwip/sockets.h>
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
struct sockaddr_in6 sa6;
|
||||
#else
|
||||
#if defined(LWS_ESP_PLATFORM)
|
||||
uint8_t _pad_sa6[28];
|
||||
#endif
|
||||
#endif
|
||||
struct sockaddr_in sa4;
|
||||
} lws_sockaddr46;
|
||||
|
||||
#define sa46_sockaddr(_sa46) ((struct sockaddr *)(_sa46))
|
||||
|
||||
#if defined(LWS_WITH_IPV6)
|
||||
#define sa46_socklen(_sa46) (socklen_t)((_sa46)->sa4.sin_family == AF_INET ? \
|
||||
sizeof(struct sockaddr_in) : \
|
||||
sizeof(struct sockaddr_in6))
|
||||
#define sa46_sockport(_sa46, _sp) { if ((_sa46)->sa4.sin_family == AF_INET) \
|
||||
(_sa46)->sa4.sin_port = (_sp); else \
|
||||
(_sa46)->sa6.sin6_port = (_sp); }
|
||||
#define sa46_address(_sa46) ((uint8_t *)((_sa46)->sa4.sin_family == AF_INET ? \
|
||||
&_sa46->sa4.sin_addr : &_sa46->sa6.sin6_addr ))
|
||||
#else
|
||||
#define sa46_socklen(_sa46) (socklen_t)sizeof(struct sockaddr_in)
|
||||
#define sa46_sockport(_sa46, _sp) (_sa46)->sa4.sin_port = (_sp)
|
||||
#define sa46_address(_sa46) (uint8_t *)&_sa46->sa4.sin_addr
|
||||
#endif
|
||||
|
||||
#define sa46_address_len(_sa46) ((_sa46)->sa4.sin_family == AF_INET ? 4 : 16)
|
||||
|
||||
#if defined(LWS_WITH_UDP)
|
||||
struct lws_udp {
|
||||
lws_sockaddr46 sa46;
|
||||
lws_sockaddr46 sa46_pending;
|
||||
uint8_t connected:1;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lws_adopt_descriptor_vhost() - adopt foreign socket or file descriptor
|
||||
* if socket descriptor, should already have been accepted from listen socket
|
||||
*
|
||||
* \param vh: lws vhost
|
||||
* \param type: OR-ed combinations of lws_adoption_type flags
|
||||
* \param fd: union with either .sockfd or .filefd set
|
||||
* \param vh_prot_name: NULL or vh protocol name to bind raw connection to
|
||||
* \param parent: NULL or struct lws to attach new_wsi to as a child
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
*
|
||||
* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's
|
||||
* ready to accept an upgrade to ws or just serve http.
|
||||
*
|
||||
* parent may be NULL, if given it should be an existing wsi that will become the
|
||||
* parent of the new wsi created by this call.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
|
||||
lws_sock_file_fd_type fd, const char *vh_prot_name,
|
||||
struct lws *parent);
|
||||
|
||||
typedef struct lws_adopt_desc {
|
||||
struct lws_vhost *vh; /**< vhost the wsi should belong to */
|
||||
lws_adoption_type type; /**< OR-ed combinations of lws_adoption_type flags */
|
||||
lws_sock_file_fd_type fd; /**< union with either .sockfd or .filefd set */
|
||||
const char *vh_prot_name; /**< NULL or vh protocol name to bind raw connection to */
|
||||
struct lws *parent; /**< NULL or struct lws to attach new_wsi to as a child */
|
||||
void *opaque; /**< opaque pointer to set on created wsi */
|
||||
const char *fi_wsi_name; /**< NULL, or Fault Injection inheritence filter for wsi=string/ context faults */
|
||||
} lws_adopt_desc_t;
|
||||
|
||||
/**
|
||||
* lws_adopt_descriptor_vhost_via_info() - adopt foreign socket or file descriptor
|
||||
* if socket descriptor, should already have been accepted from listen socket
|
||||
*
|
||||
* \param info: the struct containing the parameters
|
||||
*
|
||||
* - vh: lws vhost
|
||||
* - type: OR-ed combinations of lws_adoption_type flags
|
||||
* - fd: union with either .sockfd or .filefd set
|
||||
* - vh_prot_name: NULL or vh protocol name to bind raw connection to
|
||||
* - parent: NULL or struct lws to attach new_wsi to as a child
|
||||
* - opaque: opaque pointer to set on created wsi
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
*
|
||||
* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's
|
||||
* ready to accept an upgrade to ws or just serve http.
|
||||
*
|
||||
* parent may be NULL, if given it should be an existing wsi that will become the
|
||||
* parent of the new wsi created by this call.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info);
|
||||
|
||||
/**
|
||||
* lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
|
||||
* for the default vhost of context.
|
||||
* \param context: lws context
|
||||
* \param accept_fd: fd of already-accepted socket to adopt
|
||||
* \param readbuf: NULL or pointer to data that must be drained before reading from
|
||||
* accept_fd
|
||||
* \param len: The length of the data held at \p readbuf
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
*
|
||||
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
|
||||
* to ws or just serve http.
|
||||
*
|
||||
* If your external code did not already read from the socket, you can use
|
||||
* lws_adopt_socket() instead.
|
||||
*
|
||||
* This api is guaranteed to use the data at \p readbuf first, before reading from
|
||||
* the socket.
|
||||
*
|
||||
* \p readbuf is limited to the size of the ah rx buf, currently 2048 bytes.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
|
||||
const char *readbuf, size_t len);
|
||||
/**
|
||||
* lws_adopt_socket_vhost_readbuf() - adopt foreign socket and first rx as if listen socket
|
||||
* accepted it for vhost.
|
||||
* \param vhost: lws vhost
|
||||
* \param accept_fd: fd of already-accepted socket to adopt
|
||||
* \param readbuf: NULL or pointer to data that must be drained before reading from accept_fd
|
||||
* \param len: The length of the data held at \p readbuf
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
*
|
||||
* LWS adopts the socket in http serving mode, it's ready to accept an upgrade
|
||||
* to ws or just serve http.
|
||||
*
|
||||
* If your external code did not already read from the socket, you can use
|
||||
* lws_adopt_socket() instead.
|
||||
*
|
||||
* This api is guaranteed to use the data at \p readbuf first, before reading from
|
||||
* the socket.
|
||||
*
|
||||
* \p readbuf is limited to the size of the ah rx buf, currently 2048 bytes.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost,
|
||||
lws_sockfd_type accept_fd, const char *readbuf,
|
||||
size_t len);
|
||||
|
||||
#define LWS_CAUDP_BIND (1 << 0)
|
||||
#define LWS_CAUDP_BROADCAST (1 << 1)
|
||||
#define LWS_CAUDP_PF_PACKET (1 << 2)
|
||||
|
||||
#if defined(LWS_WITH_UDP)
|
||||
/**
|
||||
* lws_create_adopt_udp() - create, bind and adopt a UDP socket
|
||||
*
|
||||
* \param vhost: lws vhost
|
||||
* \param ads: NULL or address to do dns lookup on
|
||||
* \param port: UDP port to bind to, -1 means unbound
|
||||
* \param flags: 0 or LWS_CAUDP_NO_BIND
|
||||
* \param protocol_name: Name of protocol on vhost to bind wsi to
|
||||
* \param ifname: NULL, for network interface name to bind socket to
|
||||
* \param parent_wsi: NULL or parent wsi new wsi will be a child of
|
||||
* \param opaque: set created wsi opaque ptr to this
|
||||
* \param retry_policy: NULL for vhost default policy else wsi specific policy
|
||||
* \param fi_wsi_name: NULL, or string to inherit Fault Injection rules in
|
||||
* form "wsi=string/rule". "wsi/rule" faults will be
|
||||
* automatically applied as well. It's done at creation
|
||||
* time so the rules can, eg, inject faults related to
|
||||
* creation.
|
||||
*
|
||||
* Either returns new wsi bound to accept_fd, or closes accept_fd and
|
||||
* returns NULL, having cleaned up any new wsi pieces.
|
||||
* */
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_create_adopt_udp(struct lws_vhost *vhost, const char *ads, int port,
|
||||
int flags, const char *protocol_name, const char *ifname,
|
||||
struct lws *parent_wsi, void *opaque,
|
||||
const lws_retry_bo_t *retry_policy, const char *fi_wsi_name);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
///@}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LWS_WITH_UDP)
|
||||
|
||||
typedef enum dns_query_type {
|
||||
LWS_ADNS_RECORD_A = 0x01,
|
||||
LWS_ADNS_RECORD_CNAME = 0x05,
|
||||
LWS_ADNS_RECORD_MX = 0x0f,
|
||||
LWS_ADNS_RECORD_AAAA = 0x1c,
|
||||
} adns_query_type_t;
|
||||
|
||||
typedef enum {
|
||||
LADNS_RET_FAILED_WSI_CLOSED = -4,
|
||||
LADNS_RET_NXDOMAIN = -3,
|
||||
LADNS_RET_TIMEDOUT = -2,
|
||||
LADNS_RET_FAILED = -1,
|
||||
LADNS_RET_FOUND,
|
||||
LADNS_RET_CONTINUING
|
||||
} lws_async_dns_retcode_t;
|
||||
|
||||
struct addrinfo;
|
||||
|
||||
typedef struct lws * (*lws_async_dns_cb_t)(struct lws *wsi, const char *ads,
|
||||
const struct addrinfo *result, int n, void *opaque);
|
||||
|
||||
/**
|
||||
* lws_async_dns_query() - perform a dns lookup using async dns
|
||||
*
|
||||
* \param context: the lws_context
|
||||
* \param tsi: thread service index (usually 0)
|
||||
* \param name: DNS name to look up
|
||||
* \param qtype: type of query (A, AAAA etc)
|
||||
* \param cb: query completion callback
|
||||
* \param wsi: wsi if the query is related to one
|
||||
*
|
||||
* Starts an asynchronous DNS lookup, on completion the \p cb callback will
|
||||
* be called.
|
||||
*
|
||||
* The reference count on the cached object is incremented for every callback
|
||||
* that was called with the cached addrinfo results.
|
||||
*
|
||||
* The cached object can't be evicted until the reference count reaches zero...
|
||||
* use lws_async_dns_freeaddrinfo() to indicate you're finsihed with the
|
||||
* results for each callback that happened with them.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN lws_async_dns_retcode_t
|
||||
lws_async_dns_query(struct lws_context *context, int tsi, const char *name,
|
||||
adns_query_type_t qtype, lws_async_dns_cb_t cb,
|
||||
struct lws *wsi, void *opaque);
|
||||
|
||||
/**
|
||||
* lws_async_dns_freeaddrinfo() - decrement refcount on cached addrinfo results
|
||||
*
|
||||
* \param pai: a pointert to a pointer to first addrinfo returned as result in the callback
|
||||
*
|
||||
* Decrements the cache object's reference count. When it reaches zero, the
|
||||
* cached object may be reaped subject to LRU rules.
|
||||
*
|
||||
* The pointer to the first addrinfo give in the argument is set to NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_async_dns_freeaddrinfo(const struct addrinfo **ai);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* I2C - bitbanged generic gpio implementation
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is like an abstract class for gpio, a real implementation provides
|
||||
* functions for the ops that use the underlying OS gpio arrangements.
|
||||
*/
|
||||
|
||||
typedef struct lws_bb_i2c {
|
||||
lws_i2c_ops_t bb_ops; /* init to lws_bb_i2c_ops */
|
||||
|
||||
/* implementation-specific members */
|
||||
|
||||
_lws_plat_gpio_t scl;
|
||||
_lws_plat_gpio_t sda;
|
||||
|
||||
const lws_gpio_ops_t *gpio;
|
||||
void (*delay)(void);
|
||||
} lws_bb_i2c_t;
|
||||
|
||||
#define lws_bb_i2c_ops \
|
||||
{ \
|
||||
.init = lws_bb_i2c_init, \
|
||||
.start = lws_bb_i2c_start, \
|
||||
.stop = lws_bb_i2c_stop, \
|
||||
.write = lws_bb_i2c_write, \
|
||||
.read = lws_bb_i2c_read, \
|
||||
.set_ack = lws_bb_i2c_set_ack, \
|
||||
}
|
||||
|
||||
int
|
||||
lws_bb_i2c_init(const lws_i2c_ops_t *octx);
|
||||
|
||||
int
|
||||
lws_bb_i2c_start(const lws_i2c_ops_t *octx);
|
||||
|
||||
void
|
||||
lws_bb_i2c_stop(const lws_i2c_ops_t *octx);
|
||||
|
||||
int
|
||||
lws_bb_i2c_write(const lws_i2c_ops_t *octx, uint8_t data);
|
||||
|
||||
int
|
||||
lws_bb_i2c_read(const lws_i2c_ops_t *octx);
|
||||
|
||||
void
|
||||
lws_bb_i2c_set_ack(const lws_i2c_ops_t *octx, int ack);
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* I2C - bitbanged generic gpio implementation
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is like an abstract class for gpio, a real implementation provides
|
||||
* functions for the ops that use the underlying OS gpio arrangements.
|
||||
*/
|
||||
|
||||
#define LWSBBSPI_FLAG_USE_NCMD3 (1 << 7)
|
||||
#define LWSBBSPI_FLAG_USE_NCMD2 (1 << 6)
|
||||
#define LWSBBSPI_FLAG_USE_NCMD1 (1 << 5)
|
||||
#define LWSBBSPI_FLAG_USE_NCMD0 (1 << 4)
|
||||
#define LWSBBSPI_FLAG_USE_NCS3 (1 << 3)
|
||||
#define LWSBBSPI_FLAG_USE_NCS2 (1 << 2)
|
||||
#define LWSBBSPI_FLAG_USE_NCS1 (1 << 1)
|
||||
#define LWSBBSPI_FLAG_USE_NCS0 (1 << 0)
|
||||
|
||||
#define LWS_SPI_BB_MAX_CH 4
|
||||
|
||||
typedef struct lws_bb_spi {
|
||||
lws_spi_ops_t bb_ops; /* init to lws_bb_spi_ops */
|
||||
|
||||
/* implementation-specific members */
|
||||
const lws_gpio_ops_t *gpio;
|
||||
|
||||
_lws_plat_gpio_t clk;
|
||||
_lws_plat_gpio_t ncs[LWS_SPI_BB_MAX_CH];
|
||||
_lws_plat_gpio_t ncmd[LWS_SPI_BB_MAX_CH];
|
||||
_lws_plat_gpio_t mosi;
|
||||
_lws_plat_gpio_t miso;
|
||||
|
||||
uint8_t flags;
|
||||
} lws_bb_spi_t;
|
||||
|
||||
#define lws_bb_spi_ops \
|
||||
.init = lws_bb_spi_init, \
|
||||
.queue = lws_bb_spi_queue
|
||||
|
||||
int
|
||||
lws_bb_spi_init(const lws_spi_ops_t *octx);
|
||||
|
||||
int
|
||||
lws_bb_spi_queue(const lws_spi_ops_t *octx, const lws_spi_desc_t *desc);
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Generic button ops
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Leverages the lws generic gpio pieces to bind gpio buttons to smd events
|
||||
*/
|
||||
|
||||
#if !defined(__LWS_BUTTON_H__)
|
||||
#define __LWS_BUTTON_H__
|
||||
|
||||
typedef uint16_t lws_button_idx_t;
|
||||
|
||||
/* actual minimum may be 1 x RTOS tick depending on platform */
|
||||
#define LWS_BUTTON_MON_TIMER_MS 5
|
||||
|
||||
typedef void (*lws_button_cb_t)(void *opaque, lws_button_idx_t idx, int state);
|
||||
|
||||
/* These are specified in ms but the granularity is LWS_BUTTON_MON_TIMER_MS,
|
||||
* which may have been rounded up to an RTOS tick depending on platform */
|
||||
|
||||
enum {
|
||||
LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK = (1 << 0)
|
||||
};
|
||||
|
||||
typedef struct lws_button_regime {
|
||||
uint16_t ms_min_down;
|
||||
uint16_t ms_min_down_longpress;
|
||||
uint16_t ms_up_settle;
|
||||
uint16_t ms_doubleclick_grace;
|
||||
uint16_t ms_repeat_down;
|
||||
uint8_t flags;
|
||||
/**< when double-click classification is enabled, clicks are delayed
|
||||
* by ms_min_down + ms_doubleclick_grace to wait and see if it will
|
||||
* become a double-click. Set LWSBTNRGMFLAG_CLASSIFY_DOUBLECLICK to
|
||||
* enable it or leave that bit at 0 to get faster single-click
|
||||
* classification.
|
||||
*/
|
||||
} lws_button_regime_t;
|
||||
|
||||
/*
|
||||
* This is the const part of the button controller, describing the static
|
||||
* bindings to gpio, and lws_smd event name information
|
||||
*/
|
||||
|
||||
typedef struct lws_button_map {
|
||||
_lws_plat_gpio_t gpio;
|
||||
const char *smd_interaction_name;
|
||||
const lws_button_regime_t *regime;
|
||||
/**< a default regime is applied if this is left NULL */
|
||||
} lws_button_map_t;
|
||||
|
||||
typedef struct lws_button_controller {
|
||||
const char *smd_bc_name;
|
||||
const lws_gpio_ops_t *gpio_ops;
|
||||
const lws_button_map_t *button_map;
|
||||
lws_button_idx_t active_state_bitmap;
|
||||
uint8_t count_buttons;
|
||||
} lws_button_controller_t;
|
||||
|
||||
struct lws_button_state; /* opaque */
|
||||
|
||||
/**
|
||||
* lws_button_controller_create() - instantiate a button controller
|
||||
*
|
||||
* \param ctx: the lws_context
|
||||
* \param controller: the static controller definition
|
||||
*
|
||||
* Instantiates a button controller from a static definition of the buttons
|
||||
* and their smd names, and active levels, and binds it to a gpio implementation
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_button_state *
|
||||
lws_button_controller_create(struct lws_context *ctx,
|
||||
const lws_button_controller_t *controller);
|
||||
|
||||
/**
|
||||
* lws_button_controller_destroy() - destroys a button controller
|
||||
*
|
||||
* \param bcs: button controller state previously created
|
||||
*
|
||||
* Disables all buttons and then destroys and frees a previously created
|
||||
* button controller.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_button_controller_destroy(struct lws_button_state *bcs);
|
||||
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN lws_button_idx_t
|
||||
lws_button_get_bit(struct lws_button_state *bcs, const char *name);
|
||||
|
||||
/*
|
||||
* lws_button_enable() - enable and disable buttons
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_button_enable(struct lws_button_state *bcs,
|
||||
lws_button_idx_t _reset, lws_button_idx_t _set);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup lws_cache_ttl Cache supporting expiry
|
||||
* ##Cache supporting expiry
|
||||
*
|
||||
* These apis let you quickly and reliably implement caches of named objects,
|
||||
* that have a "destroy-by date" and cache limits that will be observed.
|
||||
*
|
||||
* You can instantiate as many caches as you need. The first one must be an
|
||||
* L1 / heap cache type, it can have parents and grandparents of other types
|
||||
* which are accessible why writing / looking up and getting from the L1 cache.
|
||||
* The outer "cache" layer may persistently store items to a backing store.
|
||||
*
|
||||
* Allocated object memory is entirely for the use of user code, up to the
|
||||
* requested size.
|
||||
*
|
||||
* The key name for the listed objects may be any string chosen by the user,
|
||||
* there is no special length limit as it is also allocated.
|
||||
*
|
||||
* Both expiry and LRU orderings are kept so it is easy to find out usage
|
||||
* ordering and when the next object that will expire.
|
||||
*
|
||||
* Cached objects may be destroyed any time you go around the event loop, when
|
||||
* you allocate new objects (to keep the whole cache under the specified limit),
|
||||
* or when their expiry time arrives. So you shouldn't keep copies of pointers
|
||||
* to cached objects after returning to the event loop.
|
||||
*/
|
||||
///@{
|
||||
|
||||
|
||||
struct lws_cache_ttl_lru;
|
||||
|
||||
/**
|
||||
* lws_cache_write_through() - add a new cache item object in all layers
|
||||
*
|
||||
* \param cache: the existing cache to allocate the object in
|
||||
* \param specific_key: a key string that identifies the item in the cache
|
||||
* \param source: optional payload for the cached item, NULL means caller will
|
||||
* write the payload
|
||||
* \param size: the size of the object to allocate
|
||||
* \param expiry: the usec time that the object will autodestroy
|
||||
* \param ppay: NULL, or a pointer to a void * to be set to the L1 payload
|
||||
*
|
||||
* If an item with the key already exists, it is destroyed before allocating a
|
||||
* new one.
|
||||
*
|
||||
* Returns 0 if successful. The written entry will be scheduled to be auto-
|
||||
* destroyed when \p expiry occurs.
|
||||
*
|
||||
* Adding or removing cache items may cause invalidation of cached queries.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int /* only valid until return to event loop */
|
||||
lws_cache_write_through(struct lws_cache_ttl_lru *cache,
|
||||
const char *specific_key, const uint8_t *source,
|
||||
size_t size, lws_usec_t expiry, void **ppay);
|
||||
|
||||
typedef struct lws_cache_match {
|
||||
lws_dll2_t list;
|
||||
lws_usec_t expiry;
|
||||
/* earliest expiry amongst results */
|
||||
size_t payload_size;
|
||||
/**< the payload is not attached here. This is a hint about what
|
||||
* (*get)() will return for this tag name.
|
||||
*/
|
||||
size_t tag_size;
|
||||
|
||||
/* tag name + NUL is overcommitted */
|
||||
} lws_cache_match_t;
|
||||
|
||||
/**
|
||||
* lws_cache_heap_lookup() - get a list of matching items
|
||||
*
|
||||
* \param cache: the cache to search for the key
|
||||
* \param wildcard_key: the item key string, may contain wildcards
|
||||
* \param pdata: pointer to pointer to be set to the serialized result list
|
||||
* \param psize: pointer to size_t to receive length of serialized result list
|
||||
*
|
||||
* This finds all unique items in the final cache that match search_key, which
|
||||
* may contain wildcards. It does not return the payloads for matching items,
|
||||
* just a list of specific tags in the that match.
|
||||
*
|
||||
* If successful, results are provided in a serialized list format, in no
|
||||
* particular order, each result has the following fields
|
||||
*
|
||||
* - BE32: payload size in bytes (payload itself is not included)
|
||||
* - BE32: specific tag name length in bytes
|
||||
* - chars: tag name with terminating NUL
|
||||
*
|
||||
* These serialized results are themselves cached in L1 cache (only) and the
|
||||
* result pointers are set pointing into that. If the results are still in L1
|
||||
* cache next time this api is called, the results will be returned directly
|
||||
* from that without repeating the expensive lookup on the backup store. That
|
||||
* is why the results are provided in serialized form.
|
||||
*
|
||||
* The cached results list expiry is set to the earliest expiry of any listed
|
||||
* item. Additionally any cached results are invalidated on addition or
|
||||
* deletion (update is done as addition + deletion) of any item that would
|
||||
* match the results' original wildcard_key. For the typical case new items
|
||||
* are rare compared to lookups, this is efficient.
|
||||
*
|
||||
* Lookup matching does not itself affect LRU or cache status of the result
|
||||
* itsems. Typically user code will get the lookup results, and then perform
|
||||
* get operations on each item in its desired order, that will bring the items
|
||||
* to the head of the LRU list and occupy L1 cache.
|
||||
*
|
||||
* Returns 0 if proceeded alright, or nonzero if error. If there was an error,
|
||||
* any partial results set has been deallocated cleanly before returning.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cache_lookup(struct lws_cache_ttl_lru *cache, const char *wildcard_key,
|
||||
const void **pdata, size_t *psize);
|
||||
|
||||
/**
|
||||
* lws_cache_item_get() - bring a specific item into L1 and get payload info
|
||||
*
|
||||
* \param cache: the cache to search for the key
|
||||
* \param specific_key: the key string of the item to get
|
||||
* \param pdata: pointer to a void * to be set to the payload in L1 cache
|
||||
* \param psize: pointer to a size_t to be set to the payload size
|
||||
*
|
||||
* If the cache still has an item matching the key string, it will be destroyed.
|
||||
*
|
||||
* Adding or removing cache items may cause invalidation of cached queries.
|
||||
*
|
||||
* Notice the cache payload is a blob of the given size. If you are storing
|
||||
* strings, there is no NUL termination unless you stored them with it.
|
||||
*
|
||||
* Returns 0 if successful.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cache_item_get(struct lws_cache_ttl_lru *cache, const char *specific_key,
|
||||
const void **pdata, size_t *psize);
|
||||
|
||||
/**
|
||||
* lws_cache_item_remove() - remove item from all cache levels
|
||||
*
|
||||
* \param cache: the cache to search for the key
|
||||
* \param wildcard_key: the item key string
|
||||
*
|
||||
* Removes any copy of any item matching the \p wildcard_key from any cache
|
||||
* level in one step.
|
||||
*
|
||||
* Adding or removing cache items may cause invalidation of cached queries
|
||||
* that could refer to the removed item.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cache_item_remove(struct lws_cache_ttl_lru *cache, const char *wildcard_key);
|
||||
|
||||
/**
|
||||
* lws_cache_footprint() - query the amount of storage used by the cache layer
|
||||
*
|
||||
* \param cache: cache to query
|
||||
*
|
||||
* Returns number of payload bytes stored in cache currently
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN uint64_t
|
||||
lws_cache_footprint(struct lws_cache_ttl_lru *cache);
|
||||
|
||||
/**
|
||||
* lws_cache_debug_dump() - if built in debug mode dump cache contents to log
|
||||
*
|
||||
* \param cache: cache to dump
|
||||
*
|
||||
* If lws was built in debug mode, dump cache to log, otherwise a NOP.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cache_debug_dump(struct lws_cache_ttl_lru *cache);
|
||||
|
||||
typedef struct lws_cache_results {
|
||||
const uint8_t *ptr; /* set before using walk api */
|
||||
size_t size; /* set before using walk api */
|
||||
|
||||
size_t payload_len;
|
||||
size_t tag_len;
|
||||
const uint8_t *tag;
|
||||
} lws_cache_results_t;
|
||||
|
||||
/**
|
||||
* lws_cache_results_walk() - parse next result
|
||||
*
|
||||
* \param walk_ctx: the context of the results blob to walk
|
||||
*
|
||||
* Caller must initialize \p walk_ctx.ptr and \p walk_ctx.size before calling.
|
||||
* These are set to the results returned from a _lookup api call.
|
||||
*
|
||||
* The call returns 0 if the struct elements have been set to a result, or 1
|
||||
* if there where no more results in the blob to walk.
|
||||
*
|
||||
* If successful, after the call \p payload_len is set to the length of the
|
||||
* payload related to this result key (the payload itself is not present),
|
||||
* \p tag_len is set to the length of the result key name, and \p tag is set
|
||||
* to the result tag name, with a terminating NUL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cache_results_walk(lws_cache_results_t *walk_ctx);
|
||||
|
||||
typedef void (*lws_cache_item_destroy_cb)(void *item, size_t size);
|
||||
struct lws_cache_creation_info {
|
||||
struct lws_context *cx;
|
||||
/**< Mandatory: the lws_context */
|
||||
const char *name;
|
||||
/**< Mandatory: short cache name */
|
||||
lws_cache_item_destroy_cb cb;
|
||||
/**< NULL, or a callback that can hook cache item destory */
|
||||
struct lws_cache_ttl_lru *parent;
|
||||
/**< NULL, or next cache level */
|
||||
const struct lws_cache_ops *ops;
|
||||
/**< NULL for default, heap-based ops, else custom cache storage and
|
||||
* query implementation */
|
||||
|
||||
union {
|
||||
struct {
|
||||
const char *filepath;
|
||||
/**< the filepath to store items in */
|
||||
} nscookiejar;
|
||||
} u;
|
||||
/**< these are extra configuration for specific cache types */
|
||||
|
||||
size_t max_footprint;
|
||||
/**< 0, or the max heap allocation allowed before destroying
|
||||
* lru items to keep it under the limit */
|
||||
size_t max_items;
|
||||
/**< 0, or the max number of items allowed in the cache before
|
||||
* destroying lru items to keep it under the limit */
|
||||
size_t max_payload;
|
||||
/**< 0, or the max allowed payload size for one item */
|
||||
int tsi;
|
||||
/**< 0 unless using SMP, then tsi to bind sul to */
|
||||
};
|
||||
|
||||
struct lws_cache_ops {
|
||||
struct lws_cache_ttl_lru *
|
||||
(*create)(const struct lws_cache_creation_info *info);
|
||||
/**< create an instance of the cache type specified in info */
|
||||
|
||||
void
|
||||
(*destroy)(struct lws_cache_ttl_lru **_cache);
|
||||
/**< destroy the logical cache instance pointed to by *_cache, doesn't
|
||||
* affect any NV backing storage */
|
||||
|
||||
int
|
||||
(*expunge)(struct lws_cache_ttl_lru *cache);
|
||||
/**< completely delete any backing storage related to the cache
|
||||
* instance, eg, delete the backing file */
|
||||
|
||||
int
|
||||
(*write)(struct lws_cache_ttl_lru *cache, const char *specific_key,
|
||||
const uint8_t *source, size_t size, lws_usec_t expiry,
|
||||
void **ppvoid);
|
||||
/**< create an entry in the cache level according to the given info */
|
||||
int
|
||||
(*tag_match)(struct lws_cache_ttl_lru *cache, const char *wc,
|
||||
const char *tag, char lookup_rules);
|
||||
/**< Just tell us if tag would match wildcard, using whatever special
|
||||
* rules the backing store might use for tag matching. 0 indicates
|
||||
* it is a match on wildcard, nonzero means does not match.
|
||||
*/
|
||||
int
|
||||
(*lookup)(struct lws_cache_ttl_lru *cache, const char *wildcard_key,
|
||||
lws_dll2_owner_t *results_owner);
|
||||
/**+ add keys for search_key matches not already listed in the results
|
||||
* owner */
|
||||
int
|
||||
(*invalidate)(struct lws_cache_ttl_lru *cache, const char *wildcard_key);
|
||||
/**< remove matching item(s) from cache level */
|
||||
|
||||
int
|
||||
(*get)(struct lws_cache_ttl_lru *cache, const char *specific_key,
|
||||
const void **pdata, size_t *psize);
|
||||
/**< if it has the item, fills L1 with item. updates LRU, and returns
|
||||
* pointer to payload in L1 */
|
||||
|
||||
void
|
||||
(*debug_dump)(struct lws_cache_ttl_lru *cache);
|
||||
/**< Helper to dump the whole cache contents to log, useful for debug */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_cache_create() - create an empty cache you can allocate items in
|
||||
*
|
||||
* \param info: a struct describing the cache to create
|
||||
*
|
||||
* Create an empty cache you can allocate items in. The cache will be kept
|
||||
* below the max_footprint and max_items limits if they are nonzero, by
|
||||
* destroying least-recently-used items until it remains below the limits.
|
||||
*
|
||||
* Items will auto-destroy when their expiry time is reached.
|
||||
*
|
||||
* When items are destroyed from the cache, if \p cb is non-NULL, it will be
|
||||
* called back with the item pointer after it has been removed from the cache,
|
||||
* but before it is deallocated and destroyed.
|
||||
*
|
||||
* context and tsi are used when scheduling expiry callbacks
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_cache_ttl_lru *
|
||||
lws_cache_create(const struct lws_cache_creation_info *info);
|
||||
|
||||
/**
|
||||
* lws_cache_destroy() - destroy a previously created cache
|
||||
*
|
||||
* \param cache: pointer to the cache
|
||||
*
|
||||
* Everything in the cache is destroyed, then the cache itself is destroyed,
|
||||
* and *cache set to NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cache_destroy(struct lws_cache_ttl_lru **cache);
|
||||
|
||||
/**
|
||||
* lws_cache_expunge() - destroy all items in cache and parents
|
||||
*
|
||||
* \param cache: pointer to the cache
|
||||
*
|
||||
* Everything in the cache and parents is destroyed, leaving it empty.
|
||||
* If the cache has a backing store, it is deleted.
|
||||
*
|
||||
* Returns 0 if no problems reported at any cache layer, else nonzero.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cache_expunge(struct lws_cache_ttl_lru *cache);
|
||||
|
||||
LWS_VISIBLE extern const struct lws_cache_ops lws_cache_ops_heap,
|
||||
lws_cache_ops_nscookiejar;
|
||||
|
||||
///@}
|
||||
|
||||
|
|
@ -1,924 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup usercb User Callback
|
||||
*
|
||||
* ##User protocol callback
|
||||
*
|
||||
* The protocol callback is the primary way lws interacts with
|
||||
* user code. For one of a list of a few dozen reasons the callback gets
|
||||
* called at some event to be handled.
|
||||
*
|
||||
* All of the events can be ignored, returning 0 is taken as "OK" and returning
|
||||
* nonzero in most cases indicates that the connection should be closed.
|
||||
*/
|
||||
///@{
|
||||
|
||||
struct lws_ssl_info {
|
||||
int where;
|
||||
int ret;
|
||||
};
|
||||
|
||||
enum lws_cert_update_state {
|
||||
LWS_CUS_IDLE,
|
||||
LWS_CUS_STARTING,
|
||||
LWS_CUS_SUCCESS,
|
||||
LWS_CUS_FAILED,
|
||||
|
||||
LWS_CUS_CREATE_KEYS,
|
||||
LWS_CUS_REG,
|
||||
LWS_CUS_AUTH,
|
||||
LWS_CUS_CHALLENGE,
|
||||
LWS_CUS_CREATE_REQ,
|
||||
LWS_CUS_REQ,
|
||||
LWS_CUS_CONFIRM,
|
||||
LWS_CUS_ISSUE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_TLS_REQ_ELEMENT_COUNTRY,
|
||||
LWS_TLS_REQ_ELEMENT_STATE,
|
||||
LWS_TLS_REQ_ELEMENT_LOCALITY,
|
||||
LWS_TLS_REQ_ELEMENT_ORGANIZATION,
|
||||
LWS_TLS_REQ_ELEMENT_COMMON_NAME,
|
||||
LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME,
|
||||
LWS_TLS_REQ_ELEMENT_EMAIL,
|
||||
|
||||
LWS_TLS_REQ_ELEMENT_COUNT,
|
||||
|
||||
LWS_TLS_SET_DIR_URL = LWS_TLS_REQ_ELEMENT_COUNT,
|
||||
LWS_TLS_SET_AUTH_PATH,
|
||||
LWS_TLS_SET_CERT_PATH,
|
||||
LWS_TLS_SET_KEY_PATH,
|
||||
|
||||
LWS_TLS_TOTAL_COUNT
|
||||
};
|
||||
|
||||
struct lws_acme_cert_aging_args {
|
||||
struct lws_vhost *vh;
|
||||
const char *element_overrides[LWS_TLS_TOTAL_COUNT]; /* NULL = use pvo */
|
||||
};
|
||||
|
||||
/*
|
||||
* With LWS_CALLBACK_FILTER_NETWORK_CONNECTION callback, user_data pointer
|
||||
* points to one of these
|
||||
*/
|
||||
|
||||
struct lws_filter_network_conn_args {
|
||||
struct sockaddr_storage cli_addr;
|
||||
socklen_t clilen;
|
||||
lws_sockfd_type accept_fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* NOTE: These public enums are part of the abi. If you want to add one,
|
||||
* add it at where specified so existing users are unaffected.
|
||||
*/
|
||||
/** enum lws_callback_reasons - reason you're getting a protocol callback */
|
||||
enum lws_callback_reasons {
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to wsi and protocol binding lifecycle -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_PROTOCOL_INIT = 27,
|
||||
/**< One-time call per protocol, per-vhost using it, so it can
|
||||
* do initial setup / allocations etc */
|
||||
|
||||
LWS_CALLBACK_PROTOCOL_DESTROY = 28,
|
||||
/**< One-time call per protocol, per-vhost using it, indicating
|
||||
* this protocol won't get used at all after this callback, the
|
||||
* vhost is getting destroyed. Take the opportunity to
|
||||
* deallocate everything that was allocated by the protocol. */
|
||||
|
||||
LWS_CALLBACK_WSI_CREATE = 29,
|
||||
/**< outermost (earliest) wsi create notification to protocols[0] */
|
||||
|
||||
LWS_CALLBACK_WSI_DESTROY = 30,
|
||||
/**< outermost (latest) wsi destroy notification to protocols[0] */
|
||||
|
||||
LWS_CALLBACK_WSI_TX_CREDIT_GET = 103,
|
||||
/**< manually-managed connection received TX credit (len is int32) */
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to Server TLS -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS = 21,
|
||||
/**< if configured for
|
||||
* including OpenSSL support, this callback allows your user code
|
||||
* to perform extra SSL_CTX_load_verify_locations() or similar
|
||||
* calls to direct OpenSSL where to find certificates the client
|
||||
* can use to confirm the remote server identity. user is the
|
||||
* OpenSSL SSL_CTX* */
|
||||
|
||||
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS = 22,
|
||||
/**< if configured for
|
||||
* including OpenSSL support, this callback allows your user code
|
||||
* to load extra certificates into the server which allow it to
|
||||
* verify the validity of certificates returned by clients. user
|
||||
* is the server's OpenSSL SSL_CTX* and in is the lws_vhost */
|
||||
|
||||
LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION = 23,
|
||||
/**< if the libwebsockets vhost was created with the option
|
||||
* LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
|
||||
* callback is generated during OpenSSL verification of the cert
|
||||
* sent from the client. It is sent to protocol[0] callback as
|
||||
* no protocol has been negotiated on the connection yet.
|
||||
* Notice that the libwebsockets context and wsi are both NULL
|
||||
* during this callback. See
|
||||
* http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
|
||||
* to understand more detail about the OpenSSL callback that
|
||||
* generates this libwebsockets callback and the meanings of the
|
||||
* arguments passed. In this callback, user is the x509_ctx,
|
||||
* in is the ssl pointer and len is preverify_ok
|
||||
* Notice that this callback maintains libwebsocket return
|
||||
* conventions, return 0 to mean the cert is OK or 1 to fail it.
|
||||
* This also means that if you don't handle this callback then
|
||||
* the default callback action of returning 0 allows the client
|
||||
* certificates. */
|
||||
|
||||
LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY = 37,
|
||||
/**< if configured for including OpenSSL support but no private key
|
||||
* file has been specified (ssl_private_key_filepath is NULL), this is
|
||||
* called to allow the user to set the private key directly via
|
||||
* libopenssl and perform further operations if required; this might be
|
||||
* useful in situations where the private key is not directly accessible
|
||||
* by the OS, for example if it is stored on a smartcard.
|
||||
* user is the server's OpenSSL SSL_CTX* */
|
||||
|
||||
LWS_CALLBACK_SSL_INFO = 67,
|
||||
/**< SSL connections only. An event you registered an
|
||||
* interest in at the vhost has occurred on a connection
|
||||
* using the vhost. in is a pointer to a
|
||||
* struct lws_ssl_info containing information about the
|
||||
* event*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to Client TLS -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION = 58,
|
||||
/**< Similar to LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION
|
||||
* this callback is called during OpenSSL verification of the cert
|
||||
* sent from the server to the client. It is sent to protocol[0]
|
||||
* callback as no protocol has been negotiated on the connection yet.
|
||||
* Notice that the wsi is set because lws_client_connect_via_info was
|
||||
* successful.
|
||||
*
|
||||
* See http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
|
||||
* to understand more detail about the OpenSSL callback that
|
||||
* generates this libwebsockets callback and the meanings of the
|
||||
* arguments passed. In this callback, user is the x509_ctx,
|
||||
* in is the ssl pointer and len is preverify_ok.
|
||||
*
|
||||
* THIS IS NOT RECOMMENDED BUT if a cert validation error shall be
|
||||
* overruled and cert shall be accepted as ok,
|
||||
* X509_STORE_CTX_set_error((X509_STORE_CTX*)user, X509_V_OK); must be
|
||||
* called and return value must be 0 to mean the cert is OK;
|
||||
* returning 1 will fail the cert in any case.
|
||||
*
|
||||
* This also means that if you don't handle this callback then
|
||||
* the default callback action of returning 0 will not accept the
|
||||
* certificate in case of a validation error decided by the SSL lib.
|
||||
*
|
||||
* This is expected and secure behaviour when validating certificates.
|
||||
*
|
||||
* Note: LCCSCF_ALLOW_SELFSIGNED and
|
||||
* LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK still work without this
|
||||
* callback being implemented.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to HTTP Server -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED = 19,
|
||||
/**< A new client has been accepted by the ws server. This
|
||||
* callback allows setting any relevant property to it. Because this
|
||||
* happens immediately after the instantiation of a new client,
|
||||
* there's no websocket protocol selected yet so this callback is
|
||||
* issued only to protocol 0. Only wsi is defined, pointing to the
|
||||
* new client, and the return value is ignored. */
|
||||
|
||||
LWS_CALLBACK_HTTP = 12,
|
||||
/**< an http request has come from a client that is not
|
||||
* asking to upgrade the connection to a websocket
|
||||
* one. This is a chance to serve http content,
|
||||
* for example, to send a script to the client
|
||||
* which will then open the websockets connection.
|
||||
* in points to the URI path requested and
|
||||
* lws_serve_http_file() makes it very
|
||||
* simple to send back a file to the client.
|
||||
* Normally after sending the file you are done
|
||||
* with the http connection, since the rest of the
|
||||
* activity will come by websockets from the script
|
||||
* that was delivered by http, so you will want to
|
||||
* return 1; to close and free up the connection. */
|
||||
|
||||
LWS_CALLBACK_HTTP_BODY = 13,
|
||||
/**< the next len bytes data from the http
|
||||
* request body HTTP connection is now available in in. */
|
||||
|
||||
LWS_CALLBACK_HTTP_BODY_COMPLETION = 14,
|
||||
/**< the expected amount of http request body has been delivered */
|
||||
|
||||
LWS_CALLBACK_HTTP_FILE_COMPLETION = 15,
|
||||
/**< a file requested to be sent down http link has completed. */
|
||||
|
||||
LWS_CALLBACK_HTTP_WRITEABLE = 16,
|
||||
/**< you can write more down the http protocol link now. */
|
||||
|
||||
LWS_CALLBACK_CLOSED_HTTP = 5,
|
||||
/**< when a HTTP (non-websocket) session ends */
|
||||
|
||||
LWS_CALLBACK_FILTER_HTTP_CONNECTION = 18,
|
||||
/**< called when the request has
|
||||
* been received and parsed from the client, but the response is
|
||||
* not sent yet. Return non-zero to disallow the connection.
|
||||
* user is a pointer to the connection user space allocation,
|
||||
* in is the URI, eg, "/"
|
||||
* In your handler you can use the public APIs
|
||||
* lws_hdr_total_length() / lws_hdr_copy() to access all of the
|
||||
* headers using the header enums lws_token_indexes from
|
||||
* libwebsockets.h to check for and read the supported header
|
||||
* presence and content before deciding to allow the http
|
||||
* connection to proceed or to kill the connection. */
|
||||
|
||||
LWS_CALLBACK_ADD_HEADERS = 53,
|
||||
/**< This gives your user code a chance to add headers to a server
|
||||
* transaction bound to your protocol. `in` points to a
|
||||
* `struct lws_process_html_args` describing a buffer and length
|
||||
* you can add headers into using the normal lws apis.
|
||||
*
|
||||
* (see LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER to add headers to
|
||||
* a client transaction)
|
||||
*
|
||||
* Only `args->p` and `args->len` are valid, and `args->p` should
|
||||
* be moved on by the amount of bytes written, if any. Eg
|
||||
*
|
||||
* case LWS_CALLBACK_ADD_HEADERS:
|
||||
*
|
||||
* struct lws_process_html_args *args =
|
||||
* (struct lws_process_html_args *)in;
|
||||
*
|
||||
* if (lws_add_http_header_by_name(wsi,
|
||||
* (unsigned char *)"set-cookie:",
|
||||
* (unsigned char *)cookie, cookie_len,
|
||||
* (unsigned char **)&args->p,
|
||||
* (unsigned char *)args->p + args->max_len))
|
||||
* return 1;
|
||||
*
|
||||
* break;
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION = 102,
|
||||
/**< This gives the user code a chance to accept or reject credentials
|
||||
* provided HTTP to basic authorization. It will only be called if the
|
||||
* http mount's authentication_mode is set to LWSAUTHM_BASIC_AUTH_CALLBACK
|
||||
* `in` points to a credential string of the form `username:password` If
|
||||
* the callback returns zero (the default if unhandled), then the
|
||||
* transaction ends with HTTP_STATUS_UNAUTHORIZED, otherwise the request
|
||||
* will be processed */
|
||||
|
||||
LWS_CALLBACK_CHECK_ACCESS_RIGHTS = 51,
|
||||
/**< This gives the user code a chance to forbid an http access.
|
||||
* `in` points to a `struct lws_process_html_args`, which
|
||||
* describes the URL, and a bit mask describing the type of
|
||||
* authentication required. If the callback returns nonzero,
|
||||
* the transaction ends with HTTP_STATUS_UNAUTHORIZED. */
|
||||
|
||||
LWS_CALLBACK_PROCESS_HTML = 52,
|
||||
/**< This gives your user code a chance to mangle outgoing
|
||||
* HTML. `in` points to a `struct lws_process_html_args`
|
||||
* which describes the buffer containing outgoing HTML.
|
||||
* The buffer may grow up to `.max_len` (currently +128
|
||||
* bytes per buffer).
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_HTTP_BIND_PROTOCOL = 49,
|
||||
/**< By default, all HTTP handling is done in protocols[0].
|
||||
* However you can bind different protocols (by name) to
|
||||
* different parts of the URL space using callback mounts. This
|
||||
* callback occurs in the new protocol when a wsi is bound
|
||||
* to that protocol. Any protocol allocation related to the
|
||||
* http transaction processing should be created then.
|
||||
* These specific callbacks are necessary because with HTTP/1.1,
|
||||
* a single connection may perform at series of different
|
||||
* transactions at different URLs, thus the lifetime of the
|
||||
* protocol bind is just for one transaction, not connection. */
|
||||
|
||||
LWS_CALLBACK_HTTP_DROP_PROTOCOL = 50,
|
||||
/**< This is called when a transaction is unbound from a protocol.
|
||||
* It indicates the connection completed its transaction and may
|
||||
* do something different now. Any protocol allocation related
|
||||
* to the http transaction processing should be destroyed. */
|
||||
|
||||
LWS_CALLBACK_HTTP_CONFIRM_UPGRADE = 86,
|
||||
/**< This is your chance to reject an HTTP upgrade action. The
|
||||
* name of the protocol being upgraded to is in 'in', and the ah
|
||||
* is still bound to the wsi, so you can look at the headers.
|
||||
*
|
||||
* The default of returning 0 (ie, also if not handled) means the
|
||||
* upgrade may proceed. Return <0 to just hang up the connection,
|
||||
* or >0 if you have rejected the connection by returning http headers
|
||||
* and response code yourself.
|
||||
*
|
||||
* There is no need for you to call transaction_completed() as the
|
||||
* caller will take care of it when it sees you returned >0.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to HTTP Client -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP = 44,
|
||||
/**< The HTTP client connection has succeeded, and is now
|
||||
* connected to the server */
|
||||
|
||||
LWS_CALLBACK_CLOSED_CLIENT_HTTP = 45,
|
||||
/**< The HTTP client connection is closing */
|
||||
|
||||
LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ = 48,
|
||||
/**< This is generated by lws_http_client_read() used to drain
|
||||
* incoming data. In the case the incoming data was chunked, it will
|
||||
* be split into multiple smaller callbacks for each chunk block,
|
||||
* removing the chunk headers. If not chunked, it will appear all in
|
||||
* one callback. */
|
||||
|
||||
LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46,
|
||||
/**< This indicates data was received on the HTTP client connection. It
|
||||
* does NOT actually drain or provide the data, so if you are doing
|
||||
* http client, you MUST handle this and call lws_http_client_read().
|
||||
* Failure to deal with it as in the minimal examples may cause spinning
|
||||
* around the event loop as it's continuously signalled the same data
|
||||
* is available for read. The related minimal examples show how to
|
||||
* handle it.
|
||||
*
|
||||
* It's possible to defer calling lws_http_client_read() if you use
|
||||
* rx flow control to stop further rx handling on the connection until
|
||||
* you did deal with it. But normally you would call it in the handler.
|
||||
*
|
||||
* lws_http_client_read() strips any chunked framing and calls back
|
||||
* with only payload data to LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ. The
|
||||
* chunking is the reason this is not just all done in one callback for
|
||||
* http.
|
||||
*/
|
||||
LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47,
|
||||
/**< The client transaction completed... at the moment this
|
||||
* is the same as closing since transaction pipelining on
|
||||
* client side is not yet supported. */
|
||||
|
||||
LWS_CALLBACK_CLIENT_HTTP_WRITEABLE = 57,
|
||||
/**< when doing an HTTP type client connection, you can call
|
||||
* lws_client_http_body_pending(wsi, 1) from
|
||||
* LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER to get these callbacks
|
||||
* sending the HTTP headers.
|
||||
*
|
||||
* From this callback, when you have sent everything, you should let
|
||||
* lws know by calling lws_client_http_body_pending(wsi, 0)
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CLIENT_HTTP_REDIRECT = 104,
|
||||
/**< we're handling a 3xx redirect... return nonzero to hang up */
|
||||
|
||||
LWS_CALLBACK_CLIENT_HTTP_BIND_PROTOCOL = 85,
|
||||
LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL = 76,
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to Websocket Server -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_ESTABLISHED = 0,
|
||||
/**< (VH) after the server completes a handshake with an incoming
|
||||
* client. If you built the library with ssl support, in is a
|
||||
* pointer to the ssl struct associated with the connection or NULL.
|
||||
*
|
||||
* b0 of len is set if the connection was made using ws-over-h2
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CLOSED = 4,
|
||||
/**< when the websocket session ends */
|
||||
|
||||
LWS_CALLBACK_SERVER_WRITEABLE = 11,
|
||||
/**< See LWS_CALLBACK_CLIENT_WRITEABLE */
|
||||
|
||||
LWS_CALLBACK_RECEIVE = 6,
|
||||
/**< data has appeared for this server endpoint from a
|
||||
* remote client, it can be found at *in and is
|
||||
* len bytes long */
|
||||
|
||||
LWS_CALLBACK_RECEIVE_PONG = 7,
|
||||
/**< servers receive PONG packets with this callback reason */
|
||||
|
||||
LWS_CALLBACK_WS_PEER_INITIATED_CLOSE = 38,
|
||||
/**< The peer has sent an unsolicited Close WS packet. in and
|
||||
* len are the optional close code (first 2 bytes, network
|
||||
* order) and the optional additional information which is not
|
||||
* defined in the standard, and may be a string or non human-readable
|
||||
* data.
|
||||
* If you return 0 lws will echo the close and then close the
|
||||
* connection. If you return nonzero lws will just close the
|
||||
* connection. */
|
||||
|
||||
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION = 20,
|
||||
/**< called when the handshake has
|
||||
* been received and parsed from the client, but the response is
|
||||
* not sent yet. Return non-zero to disallow the connection.
|
||||
* user is a pointer to the connection user space allocation,
|
||||
* in is the requested protocol name
|
||||
* In your handler you can use the public APIs
|
||||
* lws_hdr_total_length() / lws_hdr_copy() to access all of the
|
||||
* headers using the header enums lws_token_indexes from
|
||||
* libwebsockets.h to check for and read the supported header
|
||||
* presence and content before deciding to allow the handshake
|
||||
* to proceed or to kill the connection. */
|
||||
|
||||
LWS_CALLBACK_CONFIRM_EXTENSION_OKAY = 25,
|
||||
/**< When the server handshake code
|
||||
* sees that it does support a requested extension, before
|
||||
* accepting the extension by additing to the list sent back to
|
||||
* the client it gives this callback just to check that it's okay
|
||||
* to use that extension. It calls back to the requested protocol
|
||||
* and with in being the extension name, len is 0 and user is
|
||||
* valid. Note though at this time the ESTABLISHED callback hasn't
|
||||
* happened yet so if you initialize user content there, user
|
||||
* content during this callback might not be useful for anything. */
|
||||
|
||||
LWS_CALLBACK_WS_SERVER_BIND_PROTOCOL = 77,
|
||||
LWS_CALLBACK_WS_SERVER_DROP_PROTOCOL = 78,
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to Websocket Client -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR = 1,
|
||||
/**< the request client connection has been unable to complete a
|
||||
* handshake with the remote server. If in is non-NULL, you can
|
||||
* find an error string of length len where it points to
|
||||
*
|
||||
* Diagnostic strings that may be returned include
|
||||
*
|
||||
* "getaddrinfo (ipv6) failed"
|
||||
* "unknown address family"
|
||||
* "getaddrinfo (ipv4) failed"
|
||||
* "set socket opts failed"
|
||||
* "insert wsi failed"
|
||||
* "lws_ssl_client_connect1 failed"
|
||||
* "lws_ssl_client_connect2 failed"
|
||||
* "Peer hung up"
|
||||
* "read failed"
|
||||
* "HS: URI missing"
|
||||
* "HS: Redirect code but no Location"
|
||||
* "HS: URI did not parse"
|
||||
* "HS: Redirect failed"
|
||||
* "HS: Server did not return 200"
|
||||
* "HS: OOM"
|
||||
* "HS: disallowed by client filter"
|
||||
* "HS: disallowed at ESTABLISHED"
|
||||
* "HS: ACCEPT missing"
|
||||
* "HS: ws upgrade response not 101"
|
||||
* "HS: UPGRADE missing"
|
||||
* "HS: Upgrade to something other than websocket"
|
||||
* "HS: CONNECTION missing"
|
||||
* "HS: UPGRADE malformed"
|
||||
* "HS: PROTOCOL malformed"
|
||||
* "HS: Cannot match protocol"
|
||||
* "HS: EXT: list too big"
|
||||
* "HS: EXT: failed setting defaults"
|
||||
* "HS: EXT: failed parsing defaults"
|
||||
* "HS: EXT: failed parsing options"
|
||||
* "HS: EXT: Rejects server options"
|
||||
* "HS: EXT: unknown ext"
|
||||
* "HS: Accept hash wrong"
|
||||
* "HS: Rejected by filter cb"
|
||||
* "HS: OOM"
|
||||
* "HS: SO_SNDBUF failed"
|
||||
* "HS: Rejected at CLIENT_ESTABLISHED"
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH = 2,
|
||||
/**< this is the last chance for the client user code to examine the
|
||||
* http headers and decide to reject the connection. If the
|
||||
* content in the headers is interesting to the
|
||||
* client (url, etc) it needs to copy it out at
|
||||
* this point since it will be destroyed before
|
||||
* the CLIENT_ESTABLISHED call */
|
||||
|
||||
LWS_CALLBACK_CLIENT_ESTABLISHED = 3,
|
||||
/**< after your client connection completed the websocket upgrade
|
||||
* handshake with the remote server */
|
||||
|
||||
LWS_CALLBACK_CLIENT_CLOSED = 75,
|
||||
/**< when a client websocket session ends */
|
||||
|
||||
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER = 24,
|
||||
/**< this callback happens
|
||||
* when a client handshake is being compiled. user is NULL,
|
||||
* in is a char **, it's pointing to a char * which holds the
|
||||
* next location in the header buffer where you can add
|
||||
* headers, and len is the remaining space in the header buffer,
|
||||
* which is typically some hundreds of bytes. So, to add a canned
|
||||
* cookie, your handler code might look similar to:
|
||||
*
|
||||
* char **p = (char **)in, *end = (*p) + len;
|
||||
*
|
||||
* if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_COOKIE,
|
||||
* (unsigned char)"a=b", 3, p, end))
|
||||
* return -1;
|
||||
*
|
||||
* See LWS_CALLBACK_ADD_HEADERS for adding headers to server
|
||||
* transactions.
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CLIENT_RECEIVE = 8,
|
||||
/**< data has appeared from the server for the client connection, it
|
||||
* can be found at *in and is len bytes long */
|
||||
|
||||
LWS_CALLBACK_CLIENT_RECEIVE_PONG = 9,
|
||||
/**< clients receive PONG packets with this callback reason */
|
||||
|
||||
LWS_CALLBACK_CLIENT_WRITEABLE = 10,
|
||||
/**< If you call lws_callback_on_writable() on a connection, you will
|
||||
* get one of these callbacks coming when the connection socket
|
||||
* is able to accept another write packet without blocking.
|
||||
* If it already was able to take another packet without blocking,
|
||||
* you'll get this callback at the next call to the service loop
|
||||
* function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
|
||||
* and servers get LWS_CALLBACK_SERVER_WRITEABLE. */
|
||||
|
||||
LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED = 26,
|
||||
/**< When a ws client
|
||||
* connection is being prepared to start a handshake to a server,
|
||||
* each supported extension is checked with protocols[0] callback
|
||||
* with this reason, giving the user code a chance to suppress the
|
||||
* claim to support that extension by returning non-zero. If
|
||||
* unhandled, by default 0 will be returned and the extension
|
||||
* support included in the header to the server. Notice this
|
||||
* callback comes to protocols[0]. */
|
||||
|
||||
LWS_CALLBACK_WS_EXT_DEFAULTS = 39,
|
||||
/**< Gives client connections an opportunity to adjust negotiated
|
||||
* extension defaults. `user` is the extension name that was
|
||||
* negotiated (eg, "permessage-deflate"). `in` points to a
|
||||
* buffer and `len` is the buffer size. The user callback can
|
||||
* set the buffer to a string describing options the extension
|
||||
* should parse. Or just ignore for defaults. */
|
||||
|
||||
|
||||
LWS_CALLBACK_FILTER_NETWORK_CONNECTION = 17,
|
||||
/**< called when a client connects to
|
||||
* the server at network level; the connection is accepted but then
|
||||
* passed to this callback to decide whether to hang up immediately
|
||||
* or not, based on the client IP.
|
||||
*
|
||||
* user_data in the callback points to a
|
||||
* struct lws_filter_network_conn_args that is prepared with the
|
||||
* sockfd, and the peer's address information.
|
||||
*
|
||||
* in contains the connection socket's descriptor.
|
||||
*
|
||||
* Since the client connection information is not available yet,
|
||||
* wsi still pointing to the main server socket.
|
||||
*
|
||||
* Return non-zero to terminate the connection before sending or
|
||||
* receiving anything. Because this happens immediately after the
|
||||
* network connection from the client, there's no websocket protocol
|
||||
* selected yet so this callback is issued only to protocol 0. */
|
||||
|
||||
LWS_CALLBACK_WS_CLIENT_BIND_PROTOCOL = 79,
|
||||
LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL = 80,
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to external poll loop integration -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_GET_THREAD_ID = 31,
|
||||
/**< lws can accept callback when writable requests from other
|
||||
* threads, if you implement this callback and return an opaque
|
||||
* current thread ID integer. */
|
||||
|
||||
/* external poll() management support */
|
||||
LWS_CALLBACK_ADD_POLL_FD = 32,
|
||||
/**< lws normally deals with its poll() or other event loop
|
||||
* internally, but in the case you are integrating with another
|
||||
* server you will need to have lws sockets share a
|
||||
* polling array with the other server. This and the other
|
||||
* POLL_FD related callbacks let you put your specialized
|
||||
* poll array interface code in the callback for protocol 0, the
|
||||
* first protocol you support, usually the HTTP protocol in the
|
||||
* serving case.
|
||||
* This callback happens when a socket needs to be
|
||||
* added to the polling loop: in points to a struct
|
||||
* lws_pollargs; the fd member of the struct is the file
|
||||
* descriptor, and events contains the active events
|
||||
*
|
||||
* If you are using the internal lws polling / event loop
|
||||
* you can just ignore these callbacks. */
|
||||
|
||||
LWS_CALLBACK_DEL_POLL_FD = 33,
|
||||
/**< This callback happens when a socket descriptor
|
||||
* needs to be removed from an external polling array. in is
|
||||
* again the struct lws_pollargs containing the fd member
|
||||
* to be removed. If you are using the internal polling
|
||||
* loop, you can just ignore it. */
|
||||
|
||||
LWS_CALLBACK_CHANGE_MODE_POLL_FD = 34,
|
||||
/**< This callback happens when lws wants to modify the events for
|
||||
* a connection.
|
||||
* in is the struct lws_pollargs with the fd to change.
|
||||
* The new event mask is in events member and the old mask is in
|
||||
* the prev_events member.
|
||||
* If you are using the internal polling loop, you can just ignore
|
||||
* it. */
|
||||
|
||||
LWS_CALLBACK_LOCK_POLL = 35,
|
||||
/**< These allow the external poll changes driven
|
||||
* by lws to participate in an external thread locking
|
||||
* scheme around the changes, so the whole thing is threadsafe.
|
||||
* These are called around three activities in the library,
|
||||
* - inserting a new wsi in the wsi / fd table (len=1)
|
||||
* - deleting a wsi from the wsi / fd table (len=1)
|
||||
* - changing a wsi's POLLIN/OUT state (len=0)
|
||||
* Locking and unlocking external synchronization objects when
|
||||
* len == 1 allows external threads to be synchronized against
|
||||
* wsi lifecycle changes if it acquires the same lock for the
|
||||
* duration of wsi dereference from the other thread context. */
|
||||
|
||||
LWS_CALLBACK_UNLOCK_POLL = 36,
|
||||
/**< See LWS_CALLBACK_LOCK_POLL, ignore if using lws internal poll */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to CGI serving -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CGI = 40,
|
||||
/**< CGI: CGI IO events on stdin / out / err are sent here on
|
||||
* protocols[0]. The provided `lws_callback_http_dummy()`
|
||||
* handles this and the callback should be directed there if
|
||||
* you use CGI. */
|
||||
|
||||
LWS_CALLBACK_CGI_TERMINATED = 41,
|
||||
/**< CGI: The related CGI process ended, this is called before
|
||||
* the wsi is closed. Used to, eg, terminate chunking.
|
||||
* The provided `lws_callback_http_dummy()`
|
||||
* handles this and the callback should be directed there if
|
||||
* you use CGI. The child PID that terminated is in len. */
|
||||
|
||||
LWS_CALLBACK_CGI_STDIN_DATA = 42,
|
||||
/**< CGI: Data is, to be sent to the CGI process stdin, eg from
|
||||
* a POST body. The provided `lws_callback_http_dummy()`
|
||||
* handles this and the callback should be directed there if
|
||||
* you use CGI. */
|
||||
|
||||
LWS_CALLBACK_CGI_STDIN_COMPLETED = 43,
|
||||
/**< CGI: no more stdin is coming. The provided
|
||||
* `lws_callback_http_dummy()` handles this and the callback
|
||||
* should be directed there if you use CGI. */
|
||||
|
||||
LWS_CALLBACK_CGI_PROCESS_ATTACH = 70,
|
||||
/**< CGI: Sent when the CGI process is spawned for the wsi. The
|
||||
* len parameter is the PID of the child process */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to Generic Sessions -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_SESSION_INFO = 54,
|
||||
/**< This is only generated by user code using generic sessions.
|
||||
* It's used to get a `struct lws_session_info` filled in by
|
||||
* generic sessions with information about the logged-in user.
|
||||
* See the messageboard sample for an example of how to use. */
|
||||
|
||||
LWS_CALLBACK_GS_EVENT = 55,
|
||||
/**< Indicates an event happened to the Generic Sessions session.
|
||||
* `in` contains a `struct lws_gs_event_args` describing the event. */
|
||||
|
||||
LWS_CALLBACK_HTTP_PMO = 56,
|
||||
/**< per-mount options for this connection, called before
|
||||
* the normal LWS_CALLBACK_HTTP when the mount has per-mount
|
||||
* options.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to RAW PROXY -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_CLI_RX = 89,
|
||||
/**< RAW mode client (outgoing) RX */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_SRV_RX = 90,
|
||||
/**< RAW mode server (listening) RX */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_CLI_CLOSE = 91,
|
||||
/**< RAW mode client (outgoing) is closing */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_SRV_CLOSE = 92,
|
||||
/**< RAW mode server (listening) is closing */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_CLI_WRITEABLE = 93,
|
||||
/**< RAW mode client (outgoing) may be written */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_SRV_WRITEABLE = 94,
|
||||
/**< RAW mode server (listening) may be written */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_CLI_ADOPT = 95,
|
||||
/**< RAW mode client (onward) accepted socket was adopted
|
||||
* (equivalent to 'wsi created') */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_SRV_ADOPT = 96,
|
||||
/**< RAW mode server (listening) accepted socket was adopted
|
||||
* (equivalent to 'wsi created') */
|
||||
|
||||
LWS_CALLBACK_RAW_PROXY_CLI_BIND_PROTOCOL = 97,
|
||||
LWS_CALLBACK_RAW_PROXY_SRV_BIND_PROTOCOL = 98,
|
||||
LWS_CALLBACK_RAW_PROXY_CLI_DROP_PROTOCOL = 99,
|
||||
LWS_CALLBACK_RAW_PROXY_SRV_DROP_PROTOCOL = 100,
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to RAW sockets -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_RAW_RX = 59,
|
||||
/**< RAW mode connection RX */
|
||||
|
||||
LWS_CALLBACK_RAW_CLOSE = 60,
|
||||
/**< RAW mode connection is closing */
|
||||
|
||||
LWS_CALLBACK_RAW_WRITEABLE = 61,
|
||||
/**< RAW mode connection may be written */
|
||||
|
||||
LWS_CALLBACK_RAW_ADOPT = 62,
|
||||
/**< RAW mode connection was adopted (equivalent to 'wsi created') */
|
||||
|
||||
LWS_CALLBACK_RAW_CONNECTED = 101,
|
||||
/**< outgoing client RAW mode connection was connected */
|
||||
|
||||
LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL = 81,
|
||||
LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL = 82,
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to RAW file handles -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_RAW_ADOPT_FILE = 63,
|
||||
/**< RAW mode file was adopted (equivalent to 'wsi created') */
|
||||
|
||||
LWS_CALLBACK_RAW_RX_FILE = 64,
|
||||
/**< This is the indication the RAW mode file has something to read.
|
||||
* This doesn't actually do the read of the file and len is always
|
||||
* 0... your code should do the read having been informed there is
|
||||
* something to read now. */
|
||||
|
||||
LWS_CALLBACK_RAW_WRITEABLE_FILE = 65,
|
||||
/**< RAW mode file is writeable */
|
||||
|
||||
LWS_CALLBACK_RAW_CLOSE_FILE = 66,
|
||||
/**< RAW mode wsi that adopted a file is closing */
|
||||
|
||||
LWS_CALLBACK_RAW_FILE_BIND_PROTOCOL = 83,
|
||||
LWS_CALLBACK_RAW_FILE_DROP_PROTOCOL = 84,
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to generic wsi events -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_TIMER = 73,
|
||||
/**< When the time elapsed after a call to
|
||||
* lws_set_timer_usecs(wsi, usecs) is up, the wsi will get one of
|
||||
* these callbacks. The deadline can be continuously extended into the
|
||||
* future by later calls to lws_set_timer_usecs() before the deadline
|
||||
* expires, or cancelled by lws_set_timer_usecs(wsi, -1);
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_EVENT_WAIT_CANCELLED = 71,
|
||||
/**< This is sent to every protocol of every vhost in response
|
||||
* to lws_cancel_service() or lws_cancel_service_pt(). This
|
||||
* callback is serialized in the lws event loop normally, even
|
||||
* if the lws_cancel_service[_pt]() call was from a different
|
||||
* thread. */
|
||||
|
||||
LWS_CALLBACK_CHILD_CLOSING = 69,
|
||||
/**< Sent to parent to notify them a child is closing / being
|
||||
* destroyed. in is the child wsi.
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_CONNECTING = 105,
|
||||
/**< Called before a socketfd is about to connect(). In is the
|
||||
* socketfd, cast to a (void *), if on a platform where the socketfd
|
||||
* is an int, recover portably using (lws_sockfd_type)(intptr_t)in.
|
||||
*
|
||||
* It's also called in SOCKS5 or http_proxy cases where the socketfd is
|
||||
* going to try to connect to its proxy.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to TLS certificate management -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_VHOST_CERT_AGING = 72,
|
||||
/**< When a vhost TLS cert has its expiry checked, this callback
|
||||
* is broadcast to every protocol of every vhost in case the
|
||||
* protocol wants to take some action with this information.
|
||||
* \p in is a pointer to a struct lws_acme_cert_aging_args,
|
||||
* and \p len is the number of days left before it expires, as
|
||||
* a (ssize_t). In the struct lws_acme_cert_aging_args, vh
|
||||
* points to the vhost the cert aging information applies to,
|
||||
* and element_overrides[] is an optional way to update information
|
||||
* from the pvos... NULL in an index means use the information from
|
||||
* from the pvo for the cert renewal, non-NULL in the array index
|
||||
* means use that pointer instead for the index. */
|
||||
|
||||
LWS_CALLBACK_VHOST_CERT_UPDATE = 74,
|
||||
/**< When a vhost TLS cert is being updated, progress is
|
||||
* reported to the vhost in question here, including completion
|
||||
* and failure. in points to optional JSON, and len represents the
|
||||
* connection state using enum lws_cert_update_state */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* ----- Callbacks related to MQTT Client -----
|
||||
*/
|
||||
|
||||
LWS_CALLBACK_MQTT_NEW_CLIENT_INSTANTIATED = 200,
|
||||
LWS_CALLBACK_MQTT_IDLE = 201,
|
||||
LWS_CALLBACK_MQTT_CLIENT_ESTABLISHED = 202,
|
||||
LWS_CALLBACK_MQTT_SUBSCRIBED = 203,
|
||||
LWS_CALLBACK_MQTT_CLIENT_WRITEABLE = 204,
|
||||
LWS_CALLBACK_MQTT_CLIENT_RX = 205,
|
||||
LWS_CALLBACK_MQTT_UNSUBSCRIBED = 206,
|
||||
LWS_CALLBACK_MQTT_DROP_PROTOCOL = 207,
|
||||
LWS_CALLBACK_MQTT_CLIENT_CLOSED = 208,
|
||||
LWS_CALLBACK_MQTT_ACK = 209,
|
||||
/**< When a message is fully sent, if QoS0 this callback is generated
|
||||
* to locally "acknowledge" it. For QoS1, this callback is only
|
||||
* generated when the matching PUBACK is received. Return nonzero to
|
||||
* close the wsi.
|
||||
*/
|
||||
LWS_CALLBACK_MQTT_RESEND = 210,
|
||||
/**< In QoS1 or QoS2, this callback is generated instead of the _ACK one
|
||||
* if we timed out waiting for a PUBACK or a PUBREC, and we must resend
|
||||
* the message. Return nonzero to close the wsi.
|
||||
*/
|
||||
LWS_CALLBACK_MQTT_UNSUBSCRIBE_TIMEOUT = 211,
|
||||
/**< When a UNSUBSCRIBE is sent, this callback is generated instead of
|
||||
* the _UNSUBSCRIBED one if we timed out waiting for a UNSUBACK.
|
||||
* Return nonzero to close the wsi.
|
||||
*/
|
||||
|
||||
/****** add new things just above ---^ ******/
|
||||
|
||||
LWS_CALLBACK_USER = 1000,
|
||||
/**< user code can use any including above without fear of clashes */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* typedef lws_callback_function() - User server actions
|
||||
* \param wsi: Opaque websocket instance pointer
|
||||
* \param reason: The reason for the call
|
||||
* \param user: Pointer to per-session user data allocated by library
|
||||
* \param in: Pointer used for some callback reasons
|
||||
* \param len: Length set for some callback reasons
|
||||
*
|
||||
* This callback is the way the user controls what is served. All the
|
||||
* protocol detail is hidden and handled by the library.
|
||||
*
|
||||
* For each connection / session there is user data allocated that is
|
||||
* pointed to by "user". You set the size of this user data area when
|
||||
* the library is initialized with lws_create_server.
|
||||
*/
|
||||
typedef int
|
||||
lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
|
||||
#define LWS_CB_REASON_AUX_BF__CGI 1
|
||||
#define LWS_CB_REASON_AUX_BF__PROXY 2
|
||||
#define LWS_CB_REASON_AUX_BF__CGI_CHUNK_END 4
|
||||
#define LWS_CB_REASON_AUX_BF__CGI_HEADERS 8
|
||||
#define LWS_CB_REASON_AUX_BF__PROXY_TRANS_END 16
|
||||
#define LWS_CB_REASON_AUX_BF__PROXY_HEADERS 32
|
||||
///@}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup cgi cgi handling
|
||||
*
|
||||
* ##CGI handling
|
||||
*
|
||||
* These functions allow low-level control over stdin/out/err of the cgi.
|
||||
*
|
||||
* However for most cases, binding the cgi to http in and out, the default
|
||||
* lws implementation already does the right thing.
|
||||
*/
|
||||
|
||||
enum lws_enum_stdinouterr {
|
||||
LWS_STDIN = 0,
|
||||
LWS_STDOUT = 1,
|
||||
LWS_STDERR = 2,
|
||||
};
|
||||
|
||||
enum lws_cgi_hdr_state {
|
||||
LCHS_HEADER,
|
||||
LCHS_CR1,
|
||||
LCHS_LF1,
|
||||
LCHS_CR2,
|
||||
LCHS_LF2,
|
||||
LHCS_RESPONSE,
|
||||
LHCS_DUMP_HEADERS,
|
||||
LHCS_PAYLOAD,
|
||||
LCHS_SINGLE_0A,
|
||||
};
|
||||
|
||||
struct lws_cgi_args {
|
||||
struct lws **stdwsi; /**< get fd with lws_get_socket_fd() */
|
||||
enum lws_enum_stdinouterr ch; /**< channel index */
|
||||
unsigned char *data; /**< for messages with payload */
|
||||
enum lws_cgi_hdr_state hdr_state; /**< track where we are in cgi headers */
|
||||
int len; /**< length */
|
||||
};
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
/**
|
||||
* lws_cgi: spawn network-connected cgi process
|
||||
*
|
||||
* \param wsi: connection to own the process
|
||||
* \param exec_array: array of "exec-name" "arg1" ... "argn" NULL
|
||||
* \param script_uri_path_len: how many chars on the left of the uri are the
|
||||
* path to the cgi, or -1 to spawn without URL-related env vars
|
||||
* \param timeout_secs: seconds script should be allowed to run
|
||||
* \param mp_cgienv: pvo list with per-vhost cgi options to put in env
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cgi(struct lws *wsi, const char * const *exec_array,
|
||||
int script_uri_path_len, int timeout_secs,
|
||||
const struct lws_protocol_vhost_options *mp_cgienv);
|
||||
|
||||
/**
|
||||
* lws_cgi_write_split_stdout_headers: write cgi output accounting for header part
|
||||
*
|
||||
* \param wsi: connection to own the process
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cgi_write_split_stdout_headers(struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_cgi_kill: terminate cgi process associated with wsi
|
||||
*
|
||||
* \param wsi: connection to own the process
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cgi_kill(struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_cgi_get_stdwsi: get wsi for stdin, stdout, or stderr
|
||||
*
|
||||
* \param wsi: parent wsi that has cgi
|
||||
* \param ch: which of LWS_STDIN, LWS_STDOUT or LWS_STDERR
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch);
|
||||
|
||||
#endif
|
||||
///@}
|
||||
|
||||
|
|
@ -1,411 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup client Client related functions
|
||||
* ##Client releated functions
|
||||
* \ingroup lwsapi
|
||||
*
|
||||
* */
|
||||
///@{
|
||||
|
||||
/** enum lws_client_connect_ssl_connection_flags - flags that may be used
|
||||
* with struct lws_client_connect_info ssl_connection member to control if
|
||||
* and how SSL checks apply to the client connection being created
|
||||
*/
|
||||
|
||||
enum lws_client_connect_ssl_connection_flags {
|
||||
LCCSCF_USE_SSL = (1 << 0),
|
||||
LCCSCF_ALLOW_SELFSIGNED = (1 << 1),
|
||||
LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK = (1 << 2),
|
||||
LCCSCF_ALLOW_EXPIRED = (1 << 3),
|
||||
LCCSCF_ALLOW_INSECURE = (1 << 4),
|
||||
LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM = (1 << 5),
|
||||
LCCSCF_H2_QUIRK_OVERFLOWS_TXCR = (1 << 6),
|
||||
LCCSCF_H2_AUTH_BEARER = (1 << 7),
|
||||
LCCSCF_H2_HEXIFY_AUTH_TOKEN = (1 << 8),
|
||||
LCCSCF_H2_MANUAL_RXFLOW = (1 << 9),
|
||||
LCCSCF_HTTP_MULTIPART_MIME = (1 << 10),
|
||||
LCCSCF_HTTP_X_WWW_FORM_URLENCODED = (1 << 11),
|
||||
LCCSCF_HTTP_NO_FOLLOW_REDIRECT = (1 << 12),
|
||||
|
||||
LCCSCF_PIPELINE = (1 << 16),
|
||||
/**< Serialize / pipeline multiple client connections
|
||||
* on a single connection where possible.
|
||||
*
|
||||
* HTTP/1.0: possible if Keep-Alive: yes sent by server
|
||||
* HTTP/1.1: always possible... uses pipelining
|
||||
* HTTP/2: always possible... uses parallel streams
|
||||
*/
|
||||
LCCSCF_MUXABLE_STREAM = (1 << 17),
|
||||
LCCSCF_H2_PRIOR_KNOWLEDGE = (1 << 18),
|
||||
LCCSCF_WAKE_SUSPEND__VALIDITY = (1 << 19),
|
||||
/* our validity checks are important enough to wake from suspend */
|
||||
LCCSCF_PRIORITIZE_READS = (1 << 20),
|
||||
/**<
|
||||
* Normally lws balances reads and writes on all connections, so both
|
||||
* are possible even on busy connections, and we go around the event
|
||||
* loop more often to facilitate that, even if there is pending data.
|
||||
*
|
||||
* This flag indicates that you want to handle any pending reads on this
|
||||
* connection without yielding the service loop for anything else. This
|
||||
* means you may block other connection processing in favour of incoming
|
||||
* data processing on this one if it receives back to back incoming rx.
|
||||
*/
|
||||
LCCSCF_SECSTREAM_CLIENT = (1 << 21),
|
||||
/**< used to mark client wsi as bound to secure stream */
|
||||
LCCSCF_SECSTREAM_PROXY_LINK = (1 << 22),
|
||||
/**< client is a link between SS client and SS proxy */
|
||||
LCCSCF_SECSTREAM_PROXY_ONWARD = (1 << 23),
|
||||
/**< client the SS proxy's onward connection */
|
||||
|
||||
LCCSCF_IP_LOW_LATENCY = (1 << 24),
|
||||
/**< set the "low delay" bit on the IP packets of this connection */
|
||||
LCCSCF_IP_HIGH_THROUGHPUT = (1 << 25),
|
||||
/**< set the "high throughput" bit on the IP packets of this
|
||||
* connection */
|
||||
LCCSCF_IP_HIGH_RELIABILITY = (1 << 26),
|
||||
/**< set the "high reliability" bit on the IP packets of this
|
||||
* connection */
|
||||
LCCSCF_IP_LOW_COST = (1 << 27),
|
||||
/**< set the "minimize monetary cost" bit on the IP packets of this
|
||||
* connection */
|
||||
LCCSCF_CONMON = (1 << 28),
|
||||
/**< If LWS_WITH_CONMON enabled for build, keeps a copy of the
|
||||
* getaddrinfo results so they can be queried subsequently */
|
||||
LCCSCF_ACCEPT_TLS_DOWNGRADE_REDIRECTS = (1 << 29),
|
||||
/**< By default lws rejects https redirecting to http. Set this
|
||||
* flag on the client connection to allow it. */
|
||||
LCCSCF_CACHE_COOKIES = (1 << 30),
|
||||
/**< If built with -DLWS_WITH_CACHE_NSCOOKIEJAR, store and reapply
|
||||
* http cookies in a Netscape Cookie Jar on this connection */
|
||||
};
|
||||
|
||||
/** struct lws_client_connect_info - parameters to connect with when using
|
||||
* lws_client_connect_via_info() */
|
||||
|
||||
struct lws_client_connect_info {
|
||||
struct lws_context *context;
|
||||
/**< lws context to create connection in */
|
||||
const char *address;
|
||||
/**< remote address to connect to */
|
||||
int port;
|
||||
/**< remote port to connect to */
|
||||
int ssl_connection;
|
||||
/**< 0, or a combination of LCCSCF_ flags */
|
||||
const char *path;
|
||||
/**< uri path */
|
||||
const char *host;
|
||||
/**< content of host header */
|
||||
const char *origin;
|
||||
/**< content of origin header */
|
||||
const char *protocol;
|
||||
/**< list of ws protocols we could accept */
|
||||
int ietf_version_or_minus_one;
|
||||
/**< deprecated: currently leave at 0 or -1 */
|
||||
void *userdata;
|
||||
/**< if non-NULL, use this as wsi user_data instead of malloc it */
|
||||
const void *client_exts;
|
||||
/**< UNUSED... provide in info.extensions at context creation time */
|
||||
const char *method;
|
||||
/**< if non-NULL, do this http method instead of ws[s] upgrade.
|
||||
* use "GET" to be a simple http client connection. "RAW" gets
|
||||
* you a connected socket that lws itself will leave alone once
|
||||
* connected. */
|
||||
struct lws *parent_wsi;
|
||||
/**< if another wsi is responsible for this connection, give it here.
|
||||
* this is used to make sure if the parent closes so do any
|
||||
* child connections first. */
|
||||
const char *uri_replace_from;
|
||||
/**< if non-NULL, when this string is found in URIs in
|
||||
* text/html content-encoding, it's replaced with uri_replace_to */
|
||||
const char *uri_replace_to;
|
||||
/**< see uri_replace_from */
|
||||
struct lws_vhost *vhost;
|
||||
/**< vhost to bind to (used to determine related SSL_CTX) */
|
||||
struct lws **pwsi;
|
||||
/**< if not NULL, store the new wsi here early in the connection
|
||||
* process. Although we return the new wsi, the call to create the
|
||||
* client connection does progress the connection somewhat and may
|
||||
* meet an error that will result in the connection being scrubbed and
|
||||
* NULL returned. While the wsi exists though, he may process a
|
||||
* callback like CLIENT_CONNECTION_ERROR with his wsi: this gives the
|
||||
* user callback a way to identify which wsi it is that faced the error
|
||||
* even before the new wsi is returned and even if ultimately no wsi
|
||||
* is returned.
|
||||
*/
|
||||
const char *iface;
|
||||
/**< NULL to allow routing on any interface, or interface name or IP
|
||||
* to bind the socket to */
|
||||
const char *local_protocol_name;
|
||||
/**< NULL: .protocol is used both to select the local protocol handler
|
||||
* to bind to and as the list of remote ws protocols we could
|
||||
* accept.
|
||||
* non-NULL: this protocol name is used to bind the connection to
|
||||
* the local protocol handler. .protocol is used for the
|
||||
* list of remote ws protocols we could accept */
|
||||
const char *alpn;
|
||||
/**< NULL: allow lws default ALPN list, from vhost if present or from
|
||||
* list of roles built into lws
|
||||
* non-NULL: require one from provided comma-separated list of alpn
|
||||
* tokens
|
||||
*/
|
||||
|
||||
struct lws_sequencer *seq;
|
||||
/**< NULL, or an lws_seq_t that wants to be given messages about
|
||||
* this wsi's lifecycle as it connects, errors or closes.
|
||||
*/
|
||||
|
||||
void *opaque_user_data;
|
||||
/**< This data has no meaning to lws but is applied to the client wsi
|
||||
* and can be retrieved by user code with lws_get_opaque_user_data().
|
||||
* It's also provided with sequencer messages if the wsi is bound to
|
||||
* an lws_seq_t.
|
||||
*/
|
||||
|
||||
const lws_retry_bo_t *retry_and_idle_policy;
|
||||
/**< optional retry and idle policy to apply to this connection.
|
||||
* Currently only the idle parts are applied to the connection.
|
||||
*/
|
||||
|
||||
int manual_initial_tx_credit;
|
||||
/**< if LCCSCF_H2_MANUAL_REFLOW is set, this becomes the initial tx
|
||||
* credit for the stream.
|
||||
*/
|
||||
|
||||
uint8_t sys_tls_client_cert;
|
||||
/**< 0 means no client cert. 1+ means apply lws_system client cert 0+
|
||||
* to the client connection.
|
||||
*/
|
||||
|
||||
uint8_t priority;
|
||||
/**< 0 means normal priority... otherwise sets the IP priority on
|
||||
* packets coming from this connection, from 1 - 7. Setting 7
|
||||
* (network management priority) requires CAP_NET_ADMIN capability but
|
||||
* the others can be set by anyone.
|
||||
*/
|
||||
|
||||
#if defined(LWS_ROLE_MQTT)
|
||||
const lws_mqtt_client_connect_param_t *mqtt_cp;
|
||||
#else
|
||||
void *mqtt_cp;
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
|
||||
lws_fi_ctx_t fic;
|
||||
/**< Attach external Fault Injection context to the client wsi,
|
||||
* hierarchy is wsi -> vhost -> context */
|
||||
#endif
|
||||
/* for convenience, available when FI disabled in build */
|
||||
const char *fi_wsi_name;
|
||||
/**< specific Fault Injection namespace name for wsi created for this
|
||||
* connection, allows targeting by "wsi=XXX/..." if you give XXX here.
|
||||
*/
|
||||
|
||||
uint16_t keep_warm_secs;
|
||||
/**< 0 means 5s. If the client connection to the endpoint becomes idle,
|
||||
* defer closing it for this many seconds in case another outgoing
|
||||
* connection to the same endpoint turns up.
|
||||
*/
|
||||
|
||||
lws_log_cx_t *log_cx;
|
||||
/**< NULL to use lws_context log context, else a pointer to a log
|
||||
* context template to take a copy of for this wsi. Used to isolate
|
||||
* wsi-specific logs into their own stream or file.
|
||||
*/
|
||||
|
||||
/* Add new things just above here ---^
|
||||
* This is part of the ABI, don't needlessly break compatibility
|
||||
*
|
||||
* The below is to ensure later library versions with new
|
||||
* members added above will see 0 (default) even if the app
|
||||
* was not built against the newer headers.
|
||||
*/
|
||||
|
||||
void *_unused[4]; /**< dummy */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_client_connect_via_info() - Connect to another websocket server
|
||||
* \param ccinfo: pointer to lws_client_connect_info struct
|
||||
*
|
||||
* This function creates a connection to a remote server using the
|
||||
* information provided in ccinfo.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
lws_client_connect_via_info(const struct lws_client_connect_info *ccinfo);
|
||||
|
||||
/**
|
||||
* lws_init_vhost_client_ssl() - also enable client SSL on an existing vhost
|
||||
*
|
||||
* \param info: client ssl related info
|
||||
* \param vhost: which vhost to initialize client ssl operations on
|
||||
*
|
||||
* You only need to call this if you plan on using SSL client connections on
|
||||
* the vhost. For non-SSL client connections, it's not necessary to call this.
|
||||
*
|
||||
* The following members of info are used during the call
|
||||
*
|
||||
* - options must have LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT set,
|
||||
* otherwise the call does nothing
|
||||
* - provided_client_ssl_ctx must be NULL to get a generated client
|
||||
* ssl context, otherwise you can pass a prepared one in by setting it
|
||||
* - ssl_cipher_list may be NULL or set to the client valid cipher list
|
||||
* - ssl_ca_filepath may be NULL or client cert filepath
|
||||
* - ssl_cert_filepath may be NULL or client cert filepath
|
||||
* - ssl_private_key_filepath may be NULL or client cert private key
|
||||
*
|
||||
* You must create your vhost explicitly if you want to use this, so you have
|
||||
* a pointer to the vhost. Create the context first with the option flag
|
||||
* LWS_SERVER_OPTION_EXPLICIT_VHOSTS and then call lws_create_vhost() with
|
||||
* the same info struct.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_init_vhost_client_ssl(const struct lws_context_creation_info *info,
|
||||
struct lws_vhost *vhost);
|
||||
/**
|
||||
* lws_http_client_read() - consume waiting received http client data
|
||||
*
|
||||
* \param wsi: client connection
|
||||
* \param buf: pointer to buffer pointer - fill with pointer to your buffer
|
||||
* \param len: pointer to chunk length - fill with max length of buffer
|
||||
*
|
||||
* This is called when the user code is notified client http data has arrived.
|
||||
* The user code may choose to delay calling it to consume the data, for example
|
||||
* waiting until an onward connection is writeable.
|
||||
*
|
||||
* For non-chunked connections, up to len bytes of buf are filled with the
|
||||
* received content. len is set to the actual amount filled before return.
|
||||
*
|
||||
* For chunked connections, the linear buffer content contains the chunking
|
||||
* headers and it cannot be passed in one lump. Instead, this function will
|
||||
* call back LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ with in pointing to the
|
||||
* chunk start and len set to the chunk length. There will be as many calls
|
||||
* as there are chunks or partial chunks in the buffer.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_http_client_read(struct lws *wsi, char **buf, int *len);
|
||||
|
||||
/**
|
||||
* lws_http_client_http_response() - get last HTTP response code
|
||||
*
|
||||
* \param wsi: client connection
|
||||
*
|
||||
* Returns the last server response code, eg, 200 for client http connections.
|
||||
*
|
||||
* You should capture this during the LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP
|
||||
* callback, because after that the memory reserved for storing the related
|
||||
* headers is freed and this value is lost.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN unsigned int
|
||||
lws_http_client_http_response(struct lws *wsi);
|
||||
|
||||
/**
|
||||
* lws_tls_client_vhost_extra_cert_mem() - add more certs to vh client tls ctx
|
||||
*
|
||||
* \param vh: the vhost to give more client certs to
|
||||
* \param der: pointer to der format additional cert
|
||||
* \param der_len: size in bytes of der
|
||||
*
|
||||
* After the vhost is created with one cert for client verification, you
|
||||
* can add additional, eg, intermediate, certs to the client tls context
|
||||
* of the vhost, for use with validating the incoming server cert(s).
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh,
|
||||
const uint8_t *der, size_t der_len);
|
||||
|
||||
/**
|
||||
* lws_client_http_body_pending() - control if client connection needs to send body
|
||||
*
|
||||
* \param wsi: client connection
|
||||
* \param something_left_to_send: nonzero if need to send more body, 0 (default)
|
||||
* if nothing more to send
|
||||
*
|
||||
* If you will send payload data with your HTTP client connection, eg, for POST,
|
||||
* when you set the related http headers in
|
||||
* LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER callback you should also call
|
||||
* this API with something_left_to_send nonzero, and call
|
||||
* lws_callback_on_writable(wsi);
|
||||
*
|
||||
* After sending the headers, lws will call your callback with
|
||||
* LWS_CALLBACK_CLIENT_HTTP_WRITEABLE reason when writable. You can send the
|
||||
* next part of the http body payload, calling lws_callback_on_writable(wsi);
|
||||
* if there is more to come, or lws_client_http_body_pending(wsi, 0); to
|
||||
* let lws know the last part is sent and the connection can move on.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_client_http_body_pending(struct lws *wsi, int something_left_to_send);
|
||||
|
||||
/**
|
||||
* lws_client_http_multipart() - issue appropriate multipart header or trailer
|
||||
*
|
||||
* \param wsi: client connection
|
||||
* \param name: multipart header name field, or NULL if end of multipart
|
||||
* \param filename: multipart header filename field, or NULL if none
|
||||
* \param content_type: multipart header content-type part, or NULL if none
|
||||
* \param p: pointer to position in buffer
|
||||
* \param end: end of buffer
|
||||
*
|
||||
* This issues a multipart mime boundary, or terminator if name = NULL.
|
||||
*
|
||||
* Returns 0 if OK or nonzero if couldn't fit in buffer
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_client_http_multipart(struct lws *wsi, const char *name,
|
||||
const char *filename, const char *content_type,
|
||||
char **p, char *end);
|
||||
|
||||
/**
|
||||
* lws_http_basic_auth_gen() - helper to encode client basic auth string
|
||||
*
|
||||
* \param user: user name
|
||||
* \param pw: password
|
||||
* \param buf: where to store base64 result
|
||||
* \param len: max usable size of buf
|
||||
*
|
||||
* Encodes a username and password in Basic Auth format for use with the
|
||||
* Authorization header. On return, buf is filled with something like
|
||||
* "Basic QWxhZGRpbjpPcGVuU2VzYW1l".
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_http_basic_auth_gen(const char *user, const char *pw, char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* lws_tls_session_is_reused() - returns nonzero if tls session was cached
|
||||
*
|
||||
* \param wsi: the wsi
|
||||
*
|
||||
* Returns zero if the tls session is fresh, else nonzero if the tls session was
|
||||
* taken from the cache. If lws is built with LWS_WITH_TLS_SESSIONS and the vhost
|
||||
* was created with the option LWS_SERVER_OPTION_ENABLE_TLS_SESSION_CACHE, then
|
||||
* on full tls session establishment of a client connection, the session is added
|
||||
* to the tls cache.
|
||||
*
|
||||
* This lets you find out if your session was new (0) or from the cache (nonzero),
|
||||
* it'a mainly useful for stats and testing.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_tls_session_is_reused(struct lws *wsi);
|
||||
|
||||
///@}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup conmon Connection Latency information
|
||||
* ## Connection Latency information
|
||||
*
|
||||
* When LWS_WITH_CONMON is enabled at build, collects detailed statistics
|
||||
* about the client connection setup latency, available to the connection
|
||||
* itself
|
||||
*/
|
||||
///@{
|
||||
|
||||
/* enough for 4191s, or just over an hour */
|
||||
typedef uint32_t lws_conmon_interval_us_t;
|
||||
|
||||
/*
|
||||
* Connection latency information... note that not all wsi actually make
|
||||
* connections, for example h2 streams after the initial one will have 0
|
||||
* for everything except ciu_txn_resp.
|
||||
*
|
||||
* If represented in JSON, it should look like this
|
||||
*
|
||||
* {
|
||||
* "peer": "46.105.127.147",
|
||||
* "dns_us": 1234,
|
||||
* "dns_disp": 1,
|
||||
* "sockconn_us": 1234,
|
||||
* "tls_us": 1234,
|
||||
* "txn_resp_us": 1234,
|
||||
* "dns":["46.105.127.147", "2001:41d0:2:ee93::1"],
|
||||
* "prot_specific": {
|
||||
* "protocol": "http",
|
||||
* "resp": 200
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The indexes in "dns_disp" are declared in lws_conmon_dns_disposition_t
|
||||
* below.
|
||||
*
|
||||
* "prot_specific" may not be present if the protocol doesn't have anything
|
||||
* to report or is not supported.
|
||||
*/
|
||||
|
||||
typedef enum lws_conmon_pcol {
|
||||
LWSCONMON_PCOL_NONE,
|
||||
LWSCONMON_PCOL_HTTP, /* .protocol_specific.http is valid */
|
||||
} lws_conmon_pcol_t;
|
||||
|
||||
typedef enum lws_conmon_dns_disposition {
|
||||
LWSCONMON_DNS_NONE,
|
||||
/**< did not attempt DNS */
|
||||
LWSCONMON_DNS_OK = 1,
|
||||
/**< DNS lookup did give results */
|
||||
LWSCONMON_DNS_SERVER_UNREACHABLE = 2,
|
||||
/**< DNS server was not reachable */
|
||||
LWSCONMON_DNS_NO_RESULT = 3
|
||||
/**< DNS server replied but nothing usable */
|
||||
} lws_conmon_dns_disposition_t;
|
||||
|
||||
struct lws_conmon {
|
||||
lws_sockaddr46 peer46;
|
||||
/**< The peer we actually connected to, if any. .peer46.sa4.sa_family
|
||||
* is either 0 if invalid, or the AF_ */
|
||||
|
||||
union {
|
||||
struct {
|
||||
int response;
|
||||
/**< h1 http response code */
|
||||
} http;
|
||||
} protocol_specific;
|
||||
/**< possibly-present protocol-specific additional information. This
|
||||
* is only valid for the first transaction after connection and does
|
||||
* not capture results for persistent or muxed connections like ws
|
||||
* messages, mqtt messages, or h2 streams */
|
||||
|
||||
struct addrinfo *dns_results_copy;
|
||||
/**< NULL, or Allocated copy of dns results, owned by this object and
|
||||
* freed when object destroyed.
|
||||
* Only set if client flag LCCSCF_CONMON applied */
|
||||
|
||||
lws_conmon_interval_us_t ciu_dns;
|
||||
/**< 0, or if a socket connection, us taken to acquire this DNS response
|
||||
*
|
||||
*/
|
||||
lws_conmon_interval_us_t ciu_sockconn;
|
||||
/**< 0, or if connection-based, the us interval between the socket
|
||||
* connect() attempt that succeeded, and the connection setup */
|
||||
lws_conmon_interval_us_t ciu_tls;
|
||||
/**< 0 if no tls, or us taken to establish the tls tunnel */
|
||||
lws_conmon_interval_us_t ciu_txn_resp;
|
||||
/**< 0, or if the protocol supports transactions, the interval between
|
||||
* sending the initial transaction request and starting to receive the
|
||||
* response */
|
||||
|
||||
lws_conmon_pcol_t pcol;
|
||||
/**< indicates which extra protocol_specific info member is valid,
|
||||
* if any */
|
||||
|
||||
lws_conmon_dns_disposition_t dns_disposition;
|
||||
/**< indicates general disposition of DNS request */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_conmon_wsi_take() - create a connection latency object from client wsi
|
||||
*
|
||||
* \param context: lws wsi
|
||||
* \param dest: conmon struct to fill
|
||||
*
|
||||
* Copies wsi conmon data into the caller's struct. Passes ownership of
|
||||
* any allocations in the addrinfo list to the caller, lws will not delete that
|
||||
* any more on wsi close after this call. The caller must call
|
||||
* lws_conmon_release() on the struct to destroy any addrinfo in the struct
|
||||
* that is prepared by this eventually but it can defer it as long as it wants.
|
||||
*
|
||||
* Other than the addrinfo list, the contents of the returned object are
|
||||
* completely selfcontained and don't point outside of the object itself, ie,
|
||||
* everything else in there remains in scope while the object itself does.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_conmon_wsi_take(struct lws *wsi, struct lws_conmon *dest);
|
||||
|
||||
/**
|
||||
* lws_conmon_release() - free any allocations in the conmon struct
|
||||
*
|
||||
* \param conmon: pointer to conmon struct
|
||||
*
|
||||
* Destroys any allocations in the conmon struct so it can go out of scope.
|
||||
* It doesn't free \p dest itself, it's designed to clean out a struct that
|
||||
* is on the stack or embedded in another object.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_conmon_release(struct lws_conmon *conmon);
|
||||
|
||||
///@}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,511 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup cose COSE apis
|
||||
* ##COSE related functions
|
||||
* \ingroup lwsaoi
|
||||
*
|
||||
* COSE RFC 8152 relates to signed and encrypted CBOR
|
||||
*/
|
||||
//@{
|
||||
|
||||
enum {
|
||||
/* RFC8152: Table 2: Common Header Parameters
|
||||
* https://www.iana.org/assignments/cose/cose.xhtml#header-parameters
|
||||
*/
|
||||
|
||||
LWSCOSE_WKL_ALG = 1, /* int / tstr */
|
||||
LWSCOSE_WKL_CRIT, /* [+ label ] */
|
||||
LWSCOSE_WKL_CONTENT_TYPE, /* tstr / uint */
|
||||
LWSCOSE_WKL_KID, /* bstr */
|
||||
LWSCOSE_WKL_IV, /* bstr */
|
||||
LWSCOSE_WKL_IV_PARTIAL, /* bstr */
|
||||
LWSCOSE_WKL_COUNTERSIG, /* COSE sig(s) */
|
||||
LWSCOSE_WKL_COUNTERSIG0 = 9, /* bstr */
|
||||
LWSCOSE_WKL_KID_CONTEXT, /* bstr */
|
||||
LWSCOSE_WKL_CUPH_NONCE = 256, /* bstr */
|
||||
LWSCOSE_WKL_CUPH_OWNER_PUBKEY = 257, /* array */
|
||||
|
||||
/* RFC8152: Table 3: key map labels */
|
||||
|
||||
LWSCOSE_WKK_KTY = 1, /* int / tstr */
|
||||
LWSCOSE_WKK_KID, /* bstr */
|
||||
LWSCOSE_WKK_ALG, /* int / tstr */
|
||||
LWSCOSE_WKK_KEY_OPS, /* [ + (int / tstr) ] */
|
||||
LWSCOSE_WKK_BASE_IV, /* bstr */
|
||||
|
||||
/* RFC8152: Table 4: Key Operation Values */
|
||||
|
||||
LWSCOSE_WKKO_SIGN = 1,
|
||||
LWSCOSE_WKKO_VERIFY,
|
||||
LWSCOSE_WKKO_ENCRYPT,
|
||||
LWSCOSE_WKKO_DECRYPT,
|
||||
LWSCOSE_WKKO_WRAP_KEY,
|
||||
LWSCOSE_WKKO_UNWRAP_KEY,
|
||||
LWSCOSE_WKKO_DERIVE_KEY,
|
||||
LWSCOSE_WKKO_DERIVE_BITS,
|
||||
LWSCOSE_WKKO_MAC_CREATE,
|
||||
LWSCOSE_WKKO_MAC_VERIFY,
|
||||
|
||||
/* RFC8152: Table 5: ECDSA algs */
|
||||
|
||||
LWSCOSE_WKAECDSA_ALG_ES256 = -7,
|
||||
LWSCOSE_WKAECDSA_ALG_ES384 = -35,
|
||||
LWSCOSE_WKAECDSA_ALG_ES512 = -36,
|
||||
|
||||
/* RFC8152: Table 6: EDDSA algs */
|
||||
|
||||
LWSCOSE_WKAEDDSA_ALG_EDDSA = -8,
|
||||
|
||||
/* RFC8152: Table 7: HMAC algs */
|
||||
|
||||
LWSCOSE_WKAHMAC_256_64 = 4,
|
||||
LWSCOSE_WKAHMAC_256_256,
|
||||
LWSCOSE_WKAHMAC_384_384,
|
||||
LWSCOSE_WKAHMAC_512_512,
|
||||
|
||||
/* RFC8152: Table 8: AES algs */
|
||||
|
||||
LWSCOSE_WKAAES_128_64 = 14,
|
||||
LWSCOSE_WKAAES_256_64,
|
||||
LWSCOSE_WKAAES_128_128 = 25,
|
||||
LWSCOSE_WKAAES_256_128,
|
||||
|
||||
/* RFC8152: Table 9: AES GCM algs */
|
||||
|
||||
LWSCOSE_WKAAESGCM_128 = 1,
|
||||
LWSCOSE_WKAAESGCM_192,
|
||||
LWSCOSE_WKAAESGCM_256,
|
||||
|
||||
/* RFC8152: Table 10: AES CCM algs */
|
||||
|
||||
LWSCOSE_WKAAESCCM_16_64_128 = 10,
|
||||
LWSCOSE_WKAAESCCM_16_64_256,
|
||||
LWSCOSE_WKAAESCCM_64_64_128,
|
||||
LWSCOSE_WKAAESCCM_64_64_256,
|
||||
LWSCOSE_WKAAESCCM_16_128_128,
|
||||
LWSCOSE_WKAAESCCM_16_128_256,
|
||||
LWSCOSE_WKAAESCCM_64_128_128,
|
||||
LWSCOSE_WKAAESCCM_64_128_256,
|
||||
|
||||
/* RFC8152: Table 11: CHACHA20 / Poly1305 */
|
||||
|
||||
LWSCOSE_WKACHACHA_POLY1305 = 24,
|
||||
|
||||
/* RFC8152: Table 13: HKDF param */
|
||||
|
||||
LWSCOSE_WKAPHKDF_SALT = -20,
|
||||
|
||||
/* RFC8152: Table 14: Context Algorithm Parameters */
|
||||
|
||||
LWSCOSE_WKAPCTX_PARTY_U_IDENTITY = -21,
|
||||
LWSCOSE_WKAPCTX_PARTY_U_NONCE = -22,
|
||||
LWSCOSE_WKAPCTX_PARTY_U_OTHER = -23,
|
||||
LWSCOSE_WKAPCTX_PARTY_V_IDENTITY = -24,
|
||||
LWSCOSE_WKAPCTX_PARTY_V_NONCE = -25,
|
||||
LWSCOSE_WKAPCTX_PARTY_V_OTHER = -26,
|
||||
|
||||
/* RFC8152: Table 15: Direct key */
|
||||
|
||||
LWSCOSE_WKK_DIRECT_CEK = -6,
|
||||
|
||||
/* RFC8152: Table 16: Direct key with KDF */
|
||||
|
||||
LWSCOSE_WKK_DIRECT_HKDF_SHA_256 = -10,
|
||||
LWSCOSE_WKK_DIRECT_HKDF_SHA_512 = -11,
|
||||
LWSCOSE_WKK_DIRECT_HKDF_AES_128 = -12,
|
||||
LWSCOSE_WKK_DIRECT_HKDF_AES_256 = -13,
|
||||
|
||||
/* RFC8152: Table 17: AES Key Wrap Algorithm Values */
|
||||
|
||||
LWSCOSE_WKK_DIRECT_HKDFKW_SHA_256 = -3,
|
||||
LWSCOSE_WKK_DIRECT_HKDFKW_SHA_512 = -4,
|
||||
LWSCOSE_WKK_DIRECT_HKDFKW_AES_128 = -5,
|
||||
|
||||
/* RFC8152: Table 18: ECDH Algorithm Values */
|
||||
|
||||
LWSCOSE_WKAECDH_ALG_ES_HKDF_256 = -25,
|
||||
LWSCOSE_WKAECDH_ALG_ES_HKDF_512 = -26,
|
||||
LWSCOSE_WKAECDH_ALG_SS_HKDF_256 = -27,
|
||||
LWSCOSE_WKAECDH_ALG_SS_HKDF_512 = -28,
|
||||
|
||||
/* RFC8152: Table 19: ECDH Algorithm Parameters */
|
||||
|
||||
LWSCOSE_WKAPECDH_EPHEMERAL_KEY = -1,
|
||||
LWSCOSE_WKAPECDH_STATIC_KEY = -2,
|
||||
LWSCOSE_WKAPECDH_STATIC_KEY_ID = -3,
|
||||
|
||||
/* RFC8152: Table 20: ECDH Algorithm Parameters with key wrap */
|
||||
|
||||
LWSCOSE_WKAPECDH_ES_A128KW = -29,
|
||||
LWSCOSE_WKAPECDH_ES_A192KW = -30,
|
||||
LWSCOSE_WKAPECDH_ES_A256KW = -31,
|
||||
LWSCOSE_WKAPECDH_SS_A128KW = -32,
|
||||
LWSCOSE_WKAPECDH_SS_A192KW = -33,
|
||||
LWSCOSE_WKAPECDH_SS_A256KW = -34,
|
||||
|
||||
/* RFC8152: Table 21: Key Type Values
|
||||
* https://www.iana.org/assignments/cose/cose.xhtml#key-type
|
||||
*/
|
||||
|
||||
LWSCOSE_WKKTV_OKP = 1,
|
||||
LWSCOSE_WKKTV_EC2 = 2,
|
||||
LWSCOSE_WKKTV_RSA = 3,
|
||||
LWSCOSE_WKKTV_SYMMETRIC = 4,
|
||||
LWSCOSE_WKKTV_HSS_LMS = 5,
|
||||
LWSCOSE_WKKTV_WALNUTDSA = 6,
|
||||
|
||||
|
||||
/* RFC8152: Table 22: Elliptic Curves
|
||||
* https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
|
||||
*/
|
||||
|
||||
LWSCOSE_WKEC_P256 = 1,
|
||||
LWSCOSE_WKEC_P384,
|
||||
LWSCOSE_WKEC_P521,
|
||||
LWSCOSE_WKEC_X25519,
|
||||
LWSCOSE_WKEC_X448,
|
||||
LWSCOSE_WKEC_ED25519,
|
||||
LWSCOSE_WKEC_ED448,
|
||||
LWSCOSE_WKEC_SECP256K1,
|
||||
|
||||
/* RFC8152: Table 23: EC Key Parameters */
|
||||
|
||||
LWSCOSE_WKECKP_CRV = -1,
|
||||
LWSCOSE_WKECKP_X = -2,
|
||||
LWSCOSE_WKECKP_Y = -3,
|
||||
LWSCOSE_WKECKP_D = -4,
|
||||
|
||||
/* RFC8152: Table 24: Octet Key Pair (OKP) Parameters */
|
||||
|
||||
LWSCOSE_WKOKP_CRV = -1,
|
||||
LWSCOSE_WKOKP_X = -2,
|
||||
LWSCOSE_WKOKP_D = -4,
|
||||
|
||||
/* Additional from
|
||||
* https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters
|
||||
*/
|
||||
|
||||
LWSCOSE_WKKPRSA_N = -1,
|
||||
LWSCOSE_WKKPRSA_E = -2,
|
||||
LWSCOSE_WKKPRSA_D = -3,
|
||||
LWSCOSE_WKKPRSA_P = -4,
|
||||
LWSCOSE_WKKPRSA_Q = -5,
|
||||
LWSCOSE_WKKPRSA_DP = -6,
|
||||
LWSCOSE_WKKPRSA_DQ = -7,
|
||||
LWSCOSE_WKKPRSA_QINV = -8,
|
||||
LWSCOSE_WKKPRSA_OTHER = -9,
|
||||
LWSCOSE_WKKPRSA_RI = -10,
|
||||
LWSCOSE_WKKPRSA_DI = -11,
|
||||
LWSCOSE_WKKPRSA_TI = -12,
|
||||
|
||||
/* RFC8152: Table 25: Symmetric Key Parameters */
|
||||
|
||||
LWSCOSE_WKSYMKP_KEY_VALUE = 4,
|
||||
|
||||
/* RFC8152: Table 26: CoAP Content-Formats for COSE */
|
||||
|
||||
LWSCOAP_CONTENTFORMAT_COSE_SIGN = 98,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_SIGN1 = 18,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT = 96,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_ENCRYPT0 = 16,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_MAC = 97,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_MAC0 = 17,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_KEY = 101,
|
||||
LWSCOAP_CONTENTFORMAT_COSE_KEY_SET = 102,
|
||||
|
||||
/* RFC8152: Table 27: Header Parameter for CounterSignature0 */
|
||||
|
||||
LWSCOSE_WKL_COUNTERSIGNATURE0 = 9, /* bstr */
|
||||
|
||||
/* RFC8812: Table 1: RSASSA-PKCS1-v1_5 Algorithm Values */
|
||||
|
||||
LWSCOSE_WKARSA_ALG_RS256 = -257, /* + SHA-256 */
|
||||
LWSCOSE_WKARSA_ALG_RS384 = -258, /* + SHA-384 */
|
||||
LWSCOSE_WKARSA_ALG_RS512 = -259, /* + SHA-512 */
|
||||
};
|
||||
|
||||
enum enum_cose_key_meta_tok {
|
||||
COSEKEY_META_KTY,
|
||||
COSEKEY_META_KID,
|
||||
COSEKEY_META_KEY_OPS,
|
||||
COSEKEY_META_BASE_IV,
|
||||
COSEKEY_META_ALG,
|
||||
|
||||
LWS_COUNT_COSE_KEY_ELEMENTS
|
||||
};
|
||||
|
||||
typedef int64_t cose_param_t;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const char *
|
||||
lws_cose_alg_to_name(cose_param_t alg);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN cose_param_t
|
||||
lws_cose_name_to_alg(const char *name);
|
||||
|
||||
/*
|
||||
* cose_key
|
||||
*/
|
||||
|
||||
typedef struct lws_cose_key {
|
||||
/* key data elements */
|
||||
struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT];
|
||||
/* generic meta key elements, like KID */
|
||||
struct lws_gencrypto_keyelem meta[LWS_COUNT_COSE_KEY_ELEMENTS];
|
||||
lws_dll2_t list; /* used when part of a set */
|
||||
int gencrypto_kty; /**< one of LWS_GENCRYPTO_KTY_ */
|
||||
cose_param_t kty;
|
||||
cose_param_t cose_alg;
|
||||
cose_param_t cose_curve;
|
||||
char private_key; /* nonzero = has private key elements */
|
||||
} lws_cose_key_t;
|
||||
|
||||
typedef int (*lws_cose_key_import_callback)(struct lws_cose_key *s, void *user);
|
||||
|
||||
/** lws_cose_jwk_import() - Create an lws_cose_key_t object from cose_key CBOR
|
||||
*
|
||||
* \param pkey_set: NULL, or a pointer to an lws_dll2_owner_t for a cose_key set
|
||||
* \param cb: callback for each jwk-processed key, or NULL if importing a single
|
||||
* key with no parent "keys" JSON
|
||||
* \param user: pointer to be passed to the callback, otherwise ignored by lws.
|
||||
* NULL if importing a single key with no parent "keys" JSON
|
||||
* \param in: a single cose_key
|
||||
* \param len: the length of the cose_key in bytes
|
||||
*
|
||||
* Creates a single lws_cose_key_t if \p pkey_set is NULL or if the incoming
|
||||
* CBOR doesn't start with an array, otherwise expects a CBOR array containing
|
||||
* zero or more cose_key CBOR, and adds each to the \p pkey_set
|
||||
* lws_dll2_owner_t struct. Created lws_cose_key_t are filled with data from
|
||||
* the COSE representation and can be used with other COSE crypto ops.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN lws_cose_key_t *
|
||||
lws_cose_key_import(lws_dll2_owner_t *pkey_set, lws_cose_key_import_callback cb,
|
||||
void *user, const uint8_t *in, size_t len);
|
||||
|
||||
/** lws_cose_key_export() - Create cose_key CBOR from an lws_cose_key_t
|
||||
*
|
||||
* \param ck: the lws_cose_key_t to export to CBOR
|
||||
* \param ctx: the CBOR writing context (same as for lws_lec_printf())
|
||||
* \param flags: 0 to export only public elements, or LWSJWKF_EXPORT_PRIVATE
|
||||
*
|
||||
* Creates an lws_jwk struct filled with data from the COSE representation.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret
|
||||
lws_cose_key_export(lws_cose_key_t *ck, lws_lec_pctx_t *ctx, int flags);
|
||||
|
||||
/**
|
||||
* lws_cose_key_generate() - generate a fresh key
|
||||
*
|
||||
* \param context: the lws_context used to get random
|
||||
* \param cose_kty: one of LWSCOSE_WKKTV_ indicating the well-known key type
|
||||
* \param use_mask: 0, or a bitfield where (1 << LWSCOSE_WKKO_...) set means valid for use
|
||||
* \param bits: key bits for RSA
|
||||
* \param curve: for EC keys, one of "P-256", "P-384" or "P-521" currently
|
||||
* \param kid: string describing the key, or NULL
|
||||
*
|
||||
* Create an lws_cose_key_t of the specified type and return it
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN lws_cose_key_t *
|
||||
lws_cose_key_generate(struct lws_context *context, cose_param_t cose_kty,
|
||||
int use_mask, int bits, const char *curve,
|
||||
const uint8_t *kid, size_t kl);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN lws_cose_key_t *
|
||||
lws_cose_key_from_set(lws_dll2_owner_t *set, const uint8_t *kid, size_t kl);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cose_key_destroy(lws_cose_key_t **ck);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cose_key_set_destroy(lws_dll2_owner_t *o);
|
||||
|
||||
/* only available in _DEBUG build */
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cose_key_dump(const lws_cose_key_t *ck);
|
||||
|
||||
/*
|
||||
* cose_sign
|
||||
*/
|
||||
|
||||
struct lws_cose_validate_context;
|
||||
|
||||
|
||||
enum lws_cose_sig_types {
|
||||
SIGTYPE_UNKNOWN,
|
||||
SIGTYPE_MULTI,
|
||||
SIGTYPE_SINGLE,
|
||||
SIGTYPE_COUNTERSIGNED, /* not yet supported */
|
||||
SIGTYPE_MAC, /* only supported for validation */
|
||||
SIGTYPE_MAC0,
|
||||
};
|
||||
|
||||
/* a list of these result objects is the output of the validation process */
|
||||
|
||||
typedef struct {
|
||||
lws_dll2_t list;
|
||||
|
||||
const lws_cose_key_t *cose_key;
|
||||
cose_param_t cose_alg;
|
||||
|
||||
int result; /* 0 = validated */
|
||||
|
||||
} lws_cose_validate_res_t;
|
||||
|
||||
enum {
|
||||
LCOSESIGEXTCB_RET_FINISHED,
|
||||
LCOSESIGEXTCB_RET_AGAIN,
|
||||
LCOSESIGEXTCB_RET_ERROR = -1
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct lws_cose_validate_context *cps;
|
||||
const uint8_t *ext;
|
||||
size_t xl;
|
||||
} lws_cose_sig_ext_pay_t;
|
||||
|
||||
typedef int (*lws_cose_sign_ext_pay_cb_t)(lws_cose_sig_ext_pay_t *x);
|
||||
typedef int (*lws_cose_validate_pay_cb_t)(struct lws_cose_validate_context *cps,
|
||||
void *opaque, const uint8_t *paychunk,
|
||||
size_t paychunk_len);
|
||||
|
||||
typedef struct lws_cose_validate_create_info {
|
||||
struct lws_context *cx;
|
||||
/**< REQUIRED: the lws context */
|
||||
lws_dll2_owner_t *keyset;
|
||||
/**< REQUIRED: one or more cose_keys */
|
||||
|
||||
enum lws_cose_sig_types sigtype;
|
||||
/**< 0 if a CBOR tag is in the sig, else one of SIGTYPE_MULTI,
|
||||
* SIGTYPE_SINGLE, etc*/
|
||||
|
||||
lws_cose_validate_pay_cb_t pay_cb;
|
||||
/**< optional: called back with unvalidated payload pieces */
|
||||
void *pay_opaque;
|
||||
/**< optional: passed into pay_cb callback along with payload chunk */
|
||||
|
||||
lws_cose_sign_ext_pay_cb_t ext_cb;
|
||||
/**< optional extra application data provision callback */
|
||||
void *ext_opaque;
|
||||
/**< optional extra application data provision callback opaque */
|
||||
size_t ext_len;
|
||||
/**< if we have extra app data, this must be set to the length of it */
|
||||
} lws_cose_validate_create_info_t;
|
||||
|
||||
/**
|
||||
* lws_cose_validate_create() - create a signature validation context
|
||||
*
|
||||
* \param info: struct describing the validation context to create
|
||||
*
|
||||
* Creates a signature validation context set up as described in \p info.
|
||||
*
|
||||
* You can then pass the signature cbor chunks to it using
|
||||
* lws_cose_validate_chunk(), finialize and get the results list using
|
||||
* lws_cose_validate_results() and destroy with lws_cose_validate_destroy().
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_cose_validate_context *
|
||||
lws_cose_validate_create(const lws_cose_validate_create_info_t *info);
|
||||
|
||||
/**
|
||||
* lws_cose_validate_chunk() - passes chunks of CBOR into the signature validator
|
||||
*
|
||||
* \param cps: the validation context
|
||||
* \param in: the chunk of CBOR (does not have to be logically complete)
|
||||
* \param in_len: number of bytes available at \p in
|
||||
*
|
||||
* Parses signature CBOR to produce a list of result objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cose_validate_chunk(struct lws_cose_validate_context *cps,
|
||||
const uint8_t *in, size_t in_len, size_t *used_in);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN lws_dll2_owner_t *
|
||||
lws_cose_validate_results(struct lws_cose_validate_context *cps);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cose_validate_destroy(struct lws_cose_validate_context **cps);
|
||||
|
||||
struct lws_cose_sign_context;
|
||||
|
||||
#define LCSC_FL_ADD_CBOR_TAG (1 << 0)
|
||||
#define LCSC_FL_ADD_CBOR_PREFER_MAC0 (1 << 1)
|
||||
|
||||
typedef struct lws_cose_sign_create_info {
|
||||
struct lws_context *cx;
|
||||
/**< REQUIRED: the lws context */
|
||||
lws_dll2_owner_t *keyset;
|
||||
/**< REQUIRED: one or more cose_keys */
|
||||
|
||||
lws_lec_pctx_t *lec;
|
||||
/**< REQUIRED: the cbor output context to emit to, user must
|
||||
* initialize with lws_lec_init() beforehand */
|
||||
|
||||
lws_cose_sign_ext_pay_cb_t ext_cb;
|
||||
/**< optional extra application data provision callback */
|
||||
void *ext_opaque;
|
||||
/**< optional extra application data provision callback opaque */
|
||||
size_t ext_len;
|
||||
/**< if we have extra app data, this must be set to the length of it */
|
||||
|
||||
size_t inline_payload_len;
|
||||
/**< REQUIRED: size of the inline payload we will provide */
|
||||
|
||||
int flags;
|
||||
/**< bitmap of LCSC_FL_* */
|
||||
enum lws_cose_sig_types sigtype;
|
||||
/**< 0, or sign type hint */
|
||||
} lws_cose_sign_create_info_t;
|
||||
|
||||
/**
|
||||
* lws_cose_sign_create() - Create a signing context
|
||||
*
|
||||
* \param info: a structure describing the signing context you want to create
|
||||
*
|
||||
* This allocates and returns a signing context created according to what is in
|
||||
* the \p info parameter.
|
||||
*
|
||||
* \p info must be prepared with the lws_context, a keyset to use, a CBOR
|
||||
* output context, and the inline payload length.
|
||||
*
|
||||
* Returns NULL on failure or the created signing context ready to add alg(s)
|
||||
* to.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_cose_sign_context *
|
||||
lws_cose_sign_create(const lws_cose_sign_create_info_t *info);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_cose_sign_add(struct lws_cose_sign_context *csc, cose_param_t alg,
|
||||
const lws_cose_key_t *ck);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret
|
||||
lws_cose_sign_payload_chunk(struct lws_cose_sign_context *csc,
|
||||
const uint8_t *in, size_t in_len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_cose_sign_destroy(struct lws_cose_sign_context **csc);
|
||||
|
||||
//@}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* must be included manually as
|
||||
*
|
||||
* #include <libwebsockets/lws-dbus.h>
|
||||
*
|
||||
* if dbus apis needed
|
||||
*/
|
||||
|
||||
#if !defined(__LWS_DBUS_H__)
|
||||
#define __LWS_DBUS_H__
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
/* helper type to simplify implementing methods as individual functions */
|
||||
typedef DBusHandlerResult (*lws_dbus_message_handler)(DBusConnection *conn,
|
||||
DBusMessage *message, DBusMessage **reply, void *d);
|
||||
|
||||
struct lws_dbus_ctx;
|
||||
typedef void (*lws_dbus_closing_t)(struct lws_dbus_ctx *ctx);
|
||||
|
||||
struct lws_dbus_ctx {
|
||||
struct lws_dll2_owner owner; /* dbusserver ctx: HEAD of accepted list */
|
||||
struct lws_dll2 next; /* dbusserver ctx: HEAD of accepted list */
|
||||
struct lws_vhost *vh; /* the vhost we logically bind to in lws */
|
||||
int tsi; /* the lws thread service index (0 if only one service
|
||||
thread as is the default */
|
||||
DBusConnection *conn;
|
||||
DBusServer *dbs;
|
||||
DBusWatch *w[4];
|
||||
DBusPendingCall *pc;
|
||||
|
||||
char hup;
|
||||
char timeouts;
|
||||
|
||||
/* cb_closing callback will be called after the connection and this
|
||||
* related ctx struct have effectively gone out of scope.
|
||||
*
|
||||
* The callback should close and clean up the connection and free the
|
||||
* ctx.
|
||||
*/
|
||||
lws_dbus_closing_t cb_closing;
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_dbus_connection_setup() - bind dbus connection object to lws event loop
|
||||
*
|
||||
* \param ctx: additional information about the connection
|
||||
* \param conn: the DBusConnection object to bind
|
||||
*
|
||||
* This configures a DBusConnection object to use lws for watchers and timeout
|
||||
* operations.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_dbus_connection_setup(struct lws_dbus_ctx *ctx, DBusConnection *conn,
|
||||
lws_dbus_closing_t cb_closing);
|
||||
|
||||
/**
|
||||
* lws_dbus_server_listen() - bind dbus connection object to lws event loop
|
||||
*
|
||||
* \param ctx: additional information about the connection
|
||||
* \param ads: the DBUS address to listen on, eg, "unix:abstract=mysocket"
|
||||
* \param err: a DBusError object to take any extra error information
|
||||
* \param new_conn: a callback function to prepare new accepted connections
|
||||
*
|
||||
* This creates a DBusServer and binds it to the lws event loop, and your
|
||||
* callback to accept new connections.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN DBusServer *
|
||||
lws_dbus_server_listen(struct lws_dbus_ctx *ctx, const char *ads,
|
||||
DBusError *err, DBusNewConnectionFunction new_conn);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup diskcache LWS disk cache
|
||||
* ## Disk cache API
|
||||
*
|
||||
* Lws provides helper apis useful if you need a disk cache containing hashed
|
||||
* files and need to delete files from it on an LRU basis to keep it below some
|
||||
* size limit.
|
||||
*
|
||||
* The API `lws_diskcache_prepare()` deals with creating the cache dir and
|
||||
* 256 subdirs, which are used according to the first two chars of the hex
|
||||
* hash of the cache file.
|
||||
*
|
||||
* `lws_diskcache_create()` and `lws_diskcache_destroy()` allocate and free
|
||||
* an opaque struct that represents the disk cache.
|
||||
*
|
||||
* `lws_diskcache_trim()` should be called at eg, 1s intervals to perform the
|
||||
* cache dir monitoring and LRU autodelete in the background lazily. It can
|
||||
* be done in its own thread or on a timer... it monitors the directories in a
|
||||
* stateful way that stats one or more file in the cache per call, and keeps
|
||||
* a list of the oldest files as it goes. When it completes a scan, if the
|
||||
* aggregate size is over the limit, it will delete oldest files first to try
|
||||
* to keep it under the limit.
|
||||
*
|
||||
* The cache size monitoring is extremely efficient in time and memory even when
|
||||
* the cache directory becomes huge.
|
||||
*
|
||||
* `lws_diskcache_query()` is used to determine if the file already exists in
|
||||
* the cache, or if it must be created. If it must be created, then the file
|
||||
* is opened using a temp name that must be converted to a findable name with
|
||||
* `lws_diskcache_finalize_name()` when the generation of the file contents are
|
||||
* complete. Aborted cached files that did not complete generation will be
|
||||
* flushed by the LRU eventually. If the file already exists, it is 'touched'
|
||||
* to make it new again and the fd returned.
|
||||
*
|
||||
*/
|
||||
///@{
|
||||
|
||||
struct lws_diskcache_scan;
|
||||
|
||||
/**
|
||||
* lws_diskcache_create() - creates an opaque struct representing the disk cache
|
||||
*
|
||||
* \param cache_dir_base: The cache dir path, eg `/var/cache/mycache`
|
||||
* \param cache_size_limit: maximum size on disk the cache is allowed to use
|
||||
*
|
||||
* This returns an opaque `struct lws_diskcache_scan *` which represents the
|
||||
* disk cache, the trim scanning state and so on. You should use
|
||||
* `lws_diskcache_destroy()` to free it to destroy it.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_diskcache_scan *
|
||||
lws_diskcache_create(const char *cache_dir_base, uint64_t cache_size_limit);
|
||||
|
||||
/**
|
||||
* lws_diskcache_destroy() - destroys the pointer returned by ...create()
|
||||
*
|
||||
* \param lds: pointer to the pointer returned by lws_diskcache_create()
|
||||
*
|
||||
* Frees *lds and any allocations it did, and then sets *lds to NULL and
|
||||
* returns.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_diskcache_destroy(struct lws_diskcache_scan **lds);
|
||||
|
||||
/**
|
||||
* lws_diskcache_prepare() - ensures the cache dir structure exists on disk
|
||||
*
|
||||
* \param cache_base_dir: The cache dir path, eg `/var/cache/mycache`
|
||||
* \param mode: octal dir mode to enforce, like 0700
|
||||
* \param uid: uid the cache dir should belong to
|
||||
*
|
||||
* This should be called while your app is still privileged. It will create
|
||||
* the cache directory structure on disk as necessary, enforce the given access
|
||||
* mode on it and set the given uid as the owner. It won't make any trouble
|
||||
* if the cache already exists.
|
||||
*
|
||||
* Typically the mode is 0700 and the owner is the user that your application
|
||||
* will transition to use when it drops root privileges.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_diskcache_prepare(const char *cache_base_dir, int mode, uid_t uid);
|
||||
|
||||
#define LWS_DISKCACHE_QUERY_NO_CACHE 0
|
||||
#define LWS_DISKCACHE_QUERY_EXISTS 1
|
||||
#define LWS_DISKCACHE_QUERY_CREATING 2
|
||||
#define LWS_DISKCACHE_QUERY_ONGOING 3 /* something else is creating it */
|
||||
|
||||
/**
|
||||
* lws_diskcache_query() - ensures the cache dir structure exists on disk
|
||||
*
|
||||
* \param lds: The opaque struct representing the disk cache
|
||||
* \param is_bot: nonzero means the request is from a bot. Don't create new cache contents if so.
|
||||
* \param hash_hex: hex string representation of the cache object hash
|
||||
* \param _fd: pointer to the fd to be set
|
||||
* \param cache: destination string to take the cache filepath
|
||||
* \param cache_len: length of the buffer at `cache`
|
||||
* \param extant_cache_len: pointer to a size_t to take any extant cached file size
|
||||
*
|
||||
* This function is called when you want to find if the hashed name already
|
||||
* exists in the cache. The possibilities for the return value are
|
||||
*
|
||||
* - LWS_DISKCACHE_QUERY_NO_CACHE: It's not in the cache and you can't create
|
||||
* it in the cache for whatever reason.
|
||||
* - LWS_DISKCACHE_QUERY_EXISTS: It exists in the cache. It's open RDONLY and
|
||||
* *_fd has been set to the file descriptor. *extant_cache_len has been set
|
||||
* to the size of the cached file in bytes. cache has been set to the
|
||||
* full filepath of the cached file. Closing _fd is your responsibility.
|
||||
* - LWS_DISKCACHE_QUERY_CREATING: It didn't exist, but a temp file has been
|
||||
* created in the cache and *_fd set to a file descriptor opened on it RDWR.
|
||||
* You should create the contents, and call `lws_diskcache_finalize_name()`
|
||||
* when it is done. Closing _fd is your responsibility.
|
||||
* - LWS_DISKCACHE_QUERY_ONGOING: not returned by this api, but you may find it
|
||||
* desirable to make a wrapper function which can handle another asynchronous
|
||||
* process that is already creating the cached file. This can be used to
|
||||
* indicate that situation externally... how to determine the same thing is
|
||||
* already being generated is out of scope of this api.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_diskcache_query(struct lws_diskcache_scan *lds, int is_bot,
|
||||
const char *hash_hex, int *_fd, char *cache, int cache_len,
|
||||
size_t *extant_cache_len);
|
||||
|
||||
/**
|
||||
* lws_diskcache_query() - ensures the cache dir structure exists on disk
|
||||
*
|
||||
* \param cache: The cache file temp name returned with LWS_DISKCACHE_QUERY_CREATING
|
||||
*
|
||||
* This renames the cache file you are creating to its final name. It should
|
||||
* be called on the temp name returned by `lws_diskcache_query()` if it gave a
|
||||
* LWS_DISKCACHE_QUERY_CREATING return, after you have filled the cache file and
|
||||
* closed it.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_diskcache_finalize_name(char *cache);
|
||||
|
||||
/**
|
||||
* lws_diskcache_trim() - performs one or more file checks in the cache for size management
|
||||
*
|
||||
* \param lds: The opaque object representing the cache
|
||||
*
|
||||
* This should be called periodically to statefully walk the cache on disk
|
||||
* collecting the oldest files. When it has visited every file, if the cache
|
||||
* is oversize it will delete the oldest files until it's back under size again.
|
||||
*
|
||||
* Each time it's called, it will look at one or more dir in the cache. If
|
||||
* called when the cache is oversize, it increases the amount of work done each
|
||||
* call until it is reduced again. Typically it will take 256 calls before it
|
||||
* deletes anything, so if called once per second, it will delete files once
|
||||
* every 4 minutes. Each call is very inexpensive both in memory and time.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_diskcache_trim(struct lws_diskcache_scan *lds);
|
||||
|
||||
|
||||
/**
|
||||
* lws_diskcache_secs_to_idle() - see how long to idle before calling trim
|
||||
*
|
||||
* \param lds: The opaque object representing the cache
|
||||
*
|
||||
* If the cache is undersize, there's no need to monitor it immediately. This
|
||||
* suggests how long to "sleep" before calling `lws_diskcache_trim()` again.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_diskcache_secs_to_idle(struct lws_diskcache_scan *lds);
|
||||
///@}
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* lws abstract display
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(__LWS_DISPLAY_H__)
|
||||
#define __LWS_DISPLAY_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint16_t lws_display_scalar;
|
||||
|
||||
/*
|
||||
* This is embedded in the actual display implementation object at the top,
|
||||
* so a pointer to this can be cast to a pointer to the implementation object
|
||||
* by any code that is specific to how it was implemented.
|
||||
*
|
||||
* Notice for the backlight / display intensity we contain pwm_ops... these can
|
||||
* be some other pwm_ops like existing gpio pwm ops, or handled in a customized
|
||||
* way like set oled contrast. Either way, the pwm level is arrived at via a
|
||||
* full set of lws_led_sequences capable of generic lws transitions
|
||||
*/
|
||||
|
||||
typedef struct lws_display {
|
||||
int (*init)(const struct lws_display *disp);
|
||||
const lws_pwm_ops_t *bl_pwm_ops;
|
||||
int (*contrast)(const struct lws_display *disp, uint8_t contrast);
|
||||
int (*blit)(const struct lws_display *disp, const uint8_t *src,
|
||||
lws_display_scalar x, lws_display_scalar y,
|
||||
lws_display_scalar w, lws_display_scalar h);
|
||||
int (*power)(const struct lws_display *disp, int state);
|
||||
|
||||
const lws_led_sequence_def_t *bl_active;
|
||||
const lws_led_sequence_def_t *bl_dim;
|
||||
const lws_led_sequence_def_t *bl_transition;
|
||||
|
||||
void *variant;
|
||||
|
||||
int bl_index;
|
||||
|
||||
lws_display_scalar w;
|
||||
/**< display surface width in pixels */
|
||||
lws_display_scalar h;
|
||||
/**< display surface height in pixels */
|
||||
|
||||
uint8_t latency_wake_ms;
|
||||
/**< ms required after wake from sleep before display usable again...
|
||||
* delay bringing up the backlight for this amount of time on wake.
|
||||
* This is managed via a sul on the event loop, not blocking. */
|
||||
} lws_display_t;
|
||||
|
||||
/*
|
||||
* This contains dynamic data related to display state
|
||||
*/
|
||||
|
||||
enum lws_display_controller_state {
|
||||
LWSDISPS_OFF,
|
||||
LWSDISPS_AUTODIMMED, /* is in pre- blanking static dim mode */
|
||||
LWSDISPS_BECOMING_ACTIVE, /* waiting for wake latency before active */
|
||||
LWSDISPS_ACTIVE, /* is active */
|
||||
LWSDISPS_GOING_OFF /* dimming then off */
|
||||
};
|
||||
|
||||
typedef struct lws_display_state {
|
||||
|
||||
lws_sorted_usec_list_t sul_autodim;
|
||||
const lws_display_t *disp;
|
||||
struct lws_context *ctx;
|
||||
|
||||
int autodim_ms;
|
||||
int off_ms;
|
||||
|
||||
struct lws_led_state *bl_lcs;
|
||||
|
||||
lws_led_state_chs_t chs;
|
||||
/* set of sequencer transition channels */
|
||||
|
||||
enum lws_display_controller_state state;
|
||||
|
||||
} lws_display_state_t;
|
||||
|
||||
/**
|
||||
* lws_display_state_init() - initialize display states
|
||||
*
|
||||
* \param lds: the display state object
|
||||
* \param ctx: the lws context
|
||||
* \param autodim_ms: ms since last active report to dim display (<0 = never)
|
||||
* \param off_ms: ms since dim to turn display off (<0 = never)
|
||||
* \param bl_lcs: the led controller instance that has the backlight
|
||||
* \param disp: generic display object we belong to
|
||||
*
|
||||
* This initializes a display's state, and sets up the optional screen auto-dim
|
||||
* and blanking on inactive, and gradual brightness change timer.
|
||||
*
|
||||
* - auto-dim then off: set autodim to some ms and off_ms to some ms
|
||||
* - auto-dim only: set autodim to some ms and off_ms to -1
|
||||
* - off-only: set autodim to some ms and off_ms to 0
|
||||
* - neither: set both autodim and off_ms to -1
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx,
|
||||
int autodim_ms, int off_ms, struct lws_led_state *bl_lcs,
|
||||
const lws_display_t *disp);
|
||||
|
||||
/**
|
||||
* lws_display_state_set_brightness() - gradually change the brightness
|
||||
*
|
||||
* \param lds: the display state we are changing
|
||||
* \param target: the target brightness to transition to
|
||||
*
|
||||
* Adjusts the brightness gradually twoards the target at 20Hz
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_display_state_set_brightness(lws_display_state_t *lds,
|
||||
const lws_led_sequence_def_t *pwmseq);
|
||||
|
||||
/*
|
||||
* lws_display_state_active() - inform the system the display is active
|
||||
*
|
||||
* \param lds: the display state we are marking as active
|
||||
*
|
||||
* Resets the auto-dim and auto-off timers and makes sure the display is on and
|
||||
* at the active brightness level
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_display_state_active(lws_display_state_t *lds);
|
||||
|
||||
/*
|
||||
* lws_display_state_off() - turns off the related display
|
||||
*
|
||||
* \param lds: the display state we are turning off
|
||||
*
|
||||
* Turns the display to least power mode or completely off if possible.
|
||||
* Disables the timers related to dimming and blanking.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_display_state_off(lws_display_state_t *lds);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup ll linked-lists
|
||||
* ##Linked list apis
|
||||
*
|
||||
* simple single and doubly-linked lists
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* lws_start_foreach_ll(): linkedlist iterator helper start
|
||||
*
|
||||
* \param type: type of iteration, eg, struct xyz *
|
||||
* \param it: iterator var name to create
|
||||
* \param start: start of list
|
||||
*
|
||||
* This helper creates an iterator and starts a while (it) {
|
||||
* loop. The iterator runs through the linked list starting at start and
|
||||
* ends when it gets a NULL.
|
||||
* The while loop should be terminated using lws_start_foreach_ll().
|
||||
*/
|
||||
#define lws_start_foreach_ll(type, it, start)\
|
||||
{ \
|
||||
type it = start; \
|
||||
while (it) {
|
||||
|
||||
/**
|
||||
* lws_end_foreach_ll(): linkedlist iterator helper end
|
||||
*
|
||||
* \param it: same iterator var name given when starting
|
||||
* \param nxt: member name in the iterator pointing to next list element
|
||||
*
|
||||
* This helper is the partner for lws_start_foreach_ll() that ends the
|
||||
* while loop.
|
||||
*/
|
||||
|
||||
#define lws_end_foreach_ll(it, nxt) \
|
||||
it = it->nxt; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_start_foreach_ll_safe(): linkedlist iterator helper start safe against delete
|
||||
*
|
||||
* \param type: type of iteration, eg, struct xyz *
|
||||
* \param it: iterator var name to create
|
||||
* \param start: start of list
|
||||
* \param nxt: member name in the iterator pointing to next list element
|
||||
*
|
||||
* This helper creates an iterator and starts a while (it) {
|
||||
* loop. The iterator runs through the linked list starting at start and
|
||||
* ends when it gets a NULL.
|
||||
* The while loop should be terminated using lws_end_foreach_ll_safe().
|
||||
* Performs storage of next increment for situations where iterator can become invalidated
|
||||
* during iteration.
|
||||
*/
|
||||
#define lws_start_foreach_ll_safe(type, it, start, nxt)\
|
||||
{ \
|
||||
type it = start; \
|
||||
while (it) { \
|
||||
type next_##it = it->nxt;
|
||||
|
||||
/**
|
||||
* lws_end_foreach_ll_safe(): linkedlist iterator helper end (pre increment storage)
|
||||
*
|
||||
* \param it: same iterator var name given when starting
|
||||
*
|
||||
* This helper is the partner for lws_start_foreach_ll_safe() that ends the
|
||||
* while loop. It uses the precreated next_ variable already stored during
|
||||
* start.
|
||||
*/
|
||||
|
||||
#define lws_end_foreach_ll_safe(it) \
|
||||
it = next_##it; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_start_foreach_llp(): linkedlist pointer iterator helper start
|
||||
*
|
||||
* \param type: type of iteration, eg, struct xyz **
|
||||
* \param it: iterator var name to create
|
||||
* \param start: start of list
|
||||
*
|
||||
* This helper creates an iterator and starts a while (it) {
|
||||
* loop. The iterator runs through the linked list starting at the
|
||||
* address of start and ends when it gets a NULL.
|
||||
* The while loop should be terminated using lws_start_foreach_llp().
|
||||
*
|
||||
* This helper variant iterates using a pointer to the previous linked-list
|
||||
* element. That allows you to easily delete list members by rewriting the
|
||||
* previous pointer to the element's next pointer.
|
||||
*/
|
||||
#define lws_start_foreach_llp(type, it, start)\
|
||||
{ \
|
||||
type it = &(start); \
|
||||
while (*(it)) {
|
||||
|
||||
#define lws_start_foreach_llp_safe(type, it, start, nxt)\
|
||||
{ \
|
||||
type it = &(start); \
|
||||
type next; \
|
||||
while (*(it)) { \
|
||||
next = &((*(it))->nxt); \
|
||||
|
||||
/**
|
||||
* lws_end_foreach_llp(): linkedlist pointer iterator helper end
|
||||
*
|
||||
* \param it: same iterator var name given when starting
|
||||
* \param nxt: member name in the iterator pointing to next list element
|
||||
*
|
||||
* This helper is the partner for lws_start_foreach_llp() that ends the
|
||||
* while loop.
|
||||
*/
|
||||
|
||||
#define lws_end_foreach_llp(it, nxt) \
|
||||
it = &(*(it))->nxt; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define lws_end_foreach_llp_safe(it) \
|
||||
it = next; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define lws_ll_fwd_insert(\
|
||||
___new_object, /* pointer to new object */ \
|
||||
___m_list, /* member for next list object ptr */ \
|
||||
___list_head /* list head */ \
|
||||
) {\
|
||||
___new_object->___m_list = ___list_head; \
|
||||
___list_head = ___new_object; \
|
||||
}
|
||||
|
||||
#define lws_ll_fwd_remove(\
|
||||
___type, /* type of listed object */ \
|
||||
___m_list, /* member for next list object ptr */ \
|
||||
___target, /* object to remove from list */ \
|
||||
___list_head /* list head */ \
|
||||
) { \
|
||||
lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \
|
||||
if (*___ppss == ___target) { \
|
||||
*___ppss = ___target->___m_list; \
|
||||
break; \
|
||||
} \
|
||||
} lws_end_foreach_llp(___ppss, ___m_list); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* doubly linked-list
|
||||
*/
|
||||
|
||||
/*
|
||||
* lws_dll2_owner / lws_dll2 : more capable version of lws_dll. Differences:
|
||||
*
|
||||
* - there's an explicit lws_dll2_owner struct which holds head, tail and
|
||||
* count of members.
|
||||
*
|
||||
* - list members all hold a pointer to their owner. So user code does not
|
||||
* have to track anything about exactly what lws_dll2_owner list the object
|
||||
* is a member of.
|
||||
*
|
||||
* - you can use lws_dll unless you want the member count or the ability to
|
||||
* not track exactly which list it's on.
|
||||
*
|
||||
* - layout is compatible with lws_dll (but lws_dll apis will not update the
|
||||
* new stuff)
|
||||
*/
|
||||
|
||||
|
||||
struct lws_dll2;
|
||||
struct lws_dll2_owner;
|
||||
|
||||
typedef struct lws_dll2 {
|
||||
struct lws_dll2 *prev;
|
||||
struct lws_dll2 *next;
|
||||
struct lws_dll2_owner *owner;
|
||||
} lws_dll2_t;
|
||||
|
||||
typedef struct lws_dll2_owner {
|
||||
struct lws_dll2 *tail;
|
||||
struct lws_dll2 *head;
|
||||
|
||||
uint32_t count;
|
||||
} lws_dll2_owner_t;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_dll2_is_detached(const struct lws_dll2 *d);
|
||||
|
||||
static LWS_INLINE const struct lws_dll2_owner *
|
||||
lws_dll2_owner(const struct lws_dll2 *d) { return d->owner; }
|
||||
|
||||
static LWS_INLINE struct lws_dll2 *
|
||||
lws_dll2_get_head(struct lws_dll2_owner *owner) { return owner->head; }
|
||||
|
||||
static LWS_INLINE struct lws_dll2 *
|
||||
lws_dll2_get_tail(struct lws_dll2_owner *owner) { return owner->tail; }
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_add_head(struct lws_dll2 *d, struct lws_dll2_owner *owner);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_add_tail(struct lws_dll2 *d, struct lws_dll2_owner *owner);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_remove(struct lws_dll2 *d);
|
||||
|
||||
typedef int (*lws_dll2_foreach_cb_t)(struct lws_dll2 *d, void *user);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_dll2_foreach_safe(struct lws_dll2_owner *owner, void *user,
|
||||
lws_dll2_foreach_cb_t cb);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_clear(struct lws_dll2 *d);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_owner_clear(struct lws_dll2_owner *d);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_add_before(struct lws_dll2 *d, struct lws_dll2 *after);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_add_sorted(lws_dll2_t *d, lws_dll2_owner_t *own,
|
||||
int (*compare)(const lws_dll2_t *d, const lws_dll2_t *i));
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dll2_add_sorted_priv(lws_dll2_t *d, lws_dll2_owner_t *own, void *priv,
|
||||
int (*compare3)(void *priv, const lws_dll2_t *d,
|
||||
const lws_dll2_t *i));
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
_lws_dll2_search_sz_pl(lws_dll2_owner_t *own, const char *name, size_t namelen,
|
||||
size_t dll2_ofs, size_t ptr_ofs);
|
||||
|
||||
/*
|
||||
* Searches objects in an owner list linearly and returns one with a given
|
||||
* member C-string matching a supplied length-provided string if it exists, else
|
||||
* NULL.
|
||||
*/
|
||||
|
||||
#define lws_dll2_search_sz_pl(own, name, namelen, type, membd2list, membptr) \
|
||||
((type *)_lws_dll2_search_sz_pl(own, name, namelen, \
|
||||
offsetof(type, membd2list), \
|
||||
offsetof(type, membptr)))
|
||||
|
||||
#if defined(_DEBUG)
|
||||
void
|
||||
lws_dll2_describe(struct lws_dll2_owner *owner, const char *desc);
|
||||
#else
|
||||
#define lws_dll2_describe(x, y)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* these are safe against the current container object getting deleted,
|
||||
* since the hold his next in a temp and go to that next. ___tmp is
|
||||
* the temp.
|
||||
*/
|
||||
|
||||
#define lws_start_foreach_dll_safe(___type, ___it, ___tmp, ___start) \
|
||||
{ \
|
||||
___type ___it = ___start; \
|
||||
while (___it) { \
|
||||
___type ___tmp = (___it)->next;
|
||||
|
||||
#define lws_end_foreach_dll_safe(___it, ___tmp) \
|
||||
___it = ___tmp; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define lws_start_foreach_dll(___type, ___it, ___start) \
|
||||
{ \
|
||||
___type ___it = ___start; \
|
||||
while (___it) {
|
||||
|
||||
#define lws_end_foreach_dll(___it) \
|
||||
___it = (___it)->next; \
|
||||
} \
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* lws_dsh (Disordered Shared Heap) is an opaque abstraction supporting a single
|
||||
* linear buffer (overallocated at end of the lws_dsh_t) which may contain
|
||||
* multiple kinds of packets that are retired out of order, and tracked by kind.
|
||||
*
|
||||
* Each kind of packet has an lws_dll2 list of its kind of packets and acts as
|
||||
* a FIFO; packets of a particular type are always retired in order. But there
|
||||
* is no requirement about the order types are retired matching the original
|
||||
* order they arrived.
|
||||
*
|
||||
* Gaps are tracked as just another kind of "packet" list.
|
||||
*
|
||||
* "allocations" (including gaps) are prepended by an lws_dsh_object_t.
|
||||
*
|
||||
* dsh may themselves be on an lws_dll2_owner list, and under memory pressure
|
||||
* allocate into other buffers on the list.
|
||||
*
|
||||
* All management structures exist inside the allocated buffer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* lws_dsh_create() - Allocate a DSH buffer
|
||||
*
|
||||
* \param owner: the owning list this dsh belongs on, or NULL if standalone
|
||||
* \param buffer_size: the allocation in bytes
|
||||
* \param count_kinds: how many separately-tracked fifos use the buffer
|
||||
*
|
||||
* This makes a single heap allocation that includes internal tracking objects
|
||||
* in the buffer. Sub-allocated objects are bound to a "kind" index and
|
||||
* managed via a FIFO for each kind.
|
||||
*
|
||||
* Every "kind" of allocation shares the same buffer space.
|
||||
*
|
||||
* Multiple buffers may be bound together in an lws_dll2 list, and if an
|
||||
* allocation cannot be satisfied by the local buffer, space can be borrowed
|
||||
* from other dsh in the same list (the local dsh FIFO tracks these "foreign"
|
||||
* allocations as if they were local).
|
||||
*
|
||||
* Returns an opaque pointer to the dsh, or NULL if allocation failed.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_dsh *
|
||||
lws_dsh_create(lws_dll2_owner_t *owner, size_t buffer_size, int count_kinds);
|
||||
|
||||
/**
|
||||
* lws_dsh_destroy() - Destroy a DSH buffer
|
||||
*
|
||||
* \param pdsh: pointer to the dsh pointer
|
||||
*
|
||||
* Deallocates the DSH and sets *pdsh to NULL.
|
||||
*
|
||||
* Before destruction, any foreign buffer usage on the part of this dsh are
|
||||
* individually freed. All dsh on the same list are walked and checked if they
|
||||
* have their own foreign allocations on the dsh buffer being destroyed. If so,
|
||||
* it attempts to migrate the allocation to a dsh that is not currently being
|
||||
* destroyed. If all else fails (basically the buffer memory is being shrunk)
|
||||
* unmigratable objects are cleanly destroyed.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dsh_destroy(struct lws_dsh **pdsh);
|
||||
|
||||
/**
|
||||
* lws_dsh_alloc_tail() - make a suballocation inside a dsh
|
||||
*
|
||||
* \param dsh: the dsh tracking the allocation
|
||||
* \param kind: the kind of allocation
|
||||
* \param src1: the first source data to copy
|
||||
* \param size1: the size of the first source data
|
||||
* \param src2: the second source data to copy (after the first), or NULL
|
||||
* \param size2: the size of the second source data
|
||||
*
|
||||
* Allocates size1 + size2 bytes in a dsh (it prefers the given dsh but will
|
||||
* borrow space from other dsh on the same list if necessary) and copies size1
|
||||
* bytes into it from src1, followed by size2 bytes from src2 if src2 isn't
|
||||
* NULL. The actual suballocation is a bit larger because of alignment and a
|
||||
* prepended management header.
|
||||
*
|
||||
* The suballocation is added to the kind-specific FIFO at the tail.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_dsh_alloc_tail(struct lws_dsh *dsh, int kind, const void *src1,
|
||||
size_t size1, const void *src2, size_t size2);
|
||||
|
||||
/**
|
||||
* lws_dsh_free() - free a suballocation from the dsh
|
||||
*
|
||||
* \param obj: a pointer to a void * that pointed to the allocated payload
|
||||
*
|
||||
* This returns the space used by \p obj in the dsh buffer to the free list
|
||||
* of the dsh the allocation came from.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dsh_free(void **obj);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lws_dsh_get_size(struct lws_dsh *dsh, int kind);
|
||||
|
||||
/**
|
||||
* lws_dsh_get_head() - get the head allocation inside the dsh
|
||||
*
|
||||
* \param dsh: the dsh tracking the allocation
|
||||
* \param kind: the kind of allocation
|
||||
* \param obj: pointer to a void * to be set to the payload
|
||||
* \param size: set to the size of the allocation
|
||||
*
|
||||
* This gets the "next" object in the kind FIFO for the dsh, and returns 0 if
|
||||
* any. If none, returns nonzero.
|
||||
*
|
||||
* This is nondestructive of the fifo or the payload. Use lws_dsh_free on
|
||||
* obj to remove the entry from the kind fifo and return the payload to the
|
||||
* free list.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_dsh_get_head(struct lws_dsh *dsh, int kind, void **obj, size_t *size);
|
||||
|
||||
/**
|
||||
* lws_dsh_describe() - DEBUG BUILDS ONLY dump the dsh to the logs
|
||||
*
|
||||
* \param dsh: the dsh to dump
|
||||
* \param desc: text that appears at the top of the dump
|
||||
*
|
||||
* Useful information for debugging lws_dsh
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_dsh_describe(struct lws_dsh *dsh, const char *desc);
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* These are exports needed by event lib plugins.
|
||||
*/
|
||||
|
||||
enum lws_event_lib_ops_flags {
|
||||
LELOF_ISPOLL = (1 >> 0),
|
||||
LELOF_DESTROY_FINAL = (1 >> 1),
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_EV_READ = (1 << 0),
|
||||
LWS_EV_WRITE = (1 << 1),
|
||||
LWS_EV_START = (1 << 2),
|
||||
LWS_EV_STOP = (1 << 3),
|
||||
};
|
||||
|
||||
struct lws_event_loop_ops {
|
||||
const char *name;
|
||||
/* event loop-specific context init during context creation */
|
||||
int (*init_context)(struct lws_context *context,
|
||||
const struct lws_context_creation_info *info);
|
||||
/* called during lws_destroy_context */
|
||||
int (*destroy_context1)(struct lws_context *context);
|
||||
/* called during lws_destroy_context2 */
|
||||
int (*destroy_context2)(struct lws_context *context);
|
||||
/* init vhost listening wsi */
|
||||
int (*init_vhost_listen_wsi)(struct lws *wsi);
|
||||
/* init the event loop for a pt */
|
||||
int (*init_pt)(struct lws_context *context, void *_loop, int tsi);
|
||||
/* called at end of first phase of close_free_wsi() */
|
||||
int (*wsi_logical_close)(struct lws *wsi);
|
||||
/* return nonzero if client connect not allowed */
|
||||
int (*check_client_connect_ok)(struct lws *wsi);
|
||||
/* close handle manually */
|
||||
void (*close_handle_manually)(struct lws *wsi);
|
||||
/* event loop accept processing */
|
||||
int (*sock_accept)(struct lws *wsi);
|
||||
/* control wsi active events */
|
||||
void (*io)(struct lws *wsi, unsigned int flags);
|
||||
/* run the event loop for a pt */
|
||||
void (*run_pt)(struct lws_context *context, int tsi);
|
||||
/* called before pt is destroyed */
|
||||
void (*destroy_pt)(struct lws_context *context, int tsi);
|
||||
/* called just before wsi is freed */
|
||||
void (*destroy_wsi)(struct lws *wsi);
|
||||
/* return nonzero if caller thread is not loop service thread */
|
||||
int (*foreign_thread)(struct lws_context *context, int tsi);
|
||||
|
||||
uint8_t flags;
|
||||
|
||||
uint16_t evlib_size_ctx;
|
||||
uint16_t evlib_size_pt;
|
||||
uint16_t evlib_size_vh;
|
||||
uint16_t evlib_size_wsi;
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_evlib_wsi_to_evlib_pt(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_evlib_tsi_to_evlib_pt(struct lws_context *ctx, int tsi);
|
||||
|
||||
/*
|
||||
* You should consider these opaque for normal user code.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_realloc(void *ptr, size_t size, const char *reason);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_vhost_destroy1(struct lws_vhost *vh);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
|
||||
const char *caller);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_vhost_foreach_listen_wsi(struct lws_context *cx, void *arg,
|
||||
lws_dll2_foreach_cb_t cb);
|
||||
|
||||
struct lws_context_per_thread;
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt);
|
||||
|
||||
#if !defined(wsi_from_fd) && !defined(WIN32) && !defined(_WIN32)
|
||||
struct lws_context;
|
||||
LWS_VISIBLE LWS_EXTERN struct lws *
|
||||
wsi_from_fd(const struct lws_context *context, int fd);
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
_lws_plat_service_forced_tsi(struct lws_context *context, int tsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_context_destroy2(struct lws_context *context);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_destroy_event_pipe(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
__lws_close_free_wsi_final(struct lws *wsi);
|
||||
|
||||
#if LWS_MAX_SMP > 1
|
||||
|
||||
struct lws_mutex_refcount {
|
||||
pthread_mutex_t lock;
|
||||
pthread_t lock_owner;
|
||||
const char *last_lock_reason;
|
||||
char lock_depth;
|
||||
char metadata;
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_mutex_refcount_assert_held(struct lws_mutex_refcount *mr);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_mutex_refcount_init(struct lws_mutex_refcount *mr);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_mutex_refcount_destroy(struct lws_mutex_refcount *mr);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_mutex_refcount_lock(struct lws_mutex_refcount *mr, const char *reason);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Fault injection api if built with LWS_WITH_SYS_FAULT_INJECTION
|
||||
*/
|
||||
|
||||
typedef struct lws_xos {
|
||||
uint64_t s[4];
|
||||
} lws_xos_t;
|
||||
|
||||
/**
|
||||
* lws_xos_init() - seed xoshiro256 PRNG
|
||||
*
|
||||
* \param xos: the prng state object to initialize
|
||||
* \param seed: the 64-bit seed
|
||||
*
|
||||
* Initialize PRNG \xos with the starting state represented by \p seed
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_xos_init(struct lws_xos *xos, uint64_t seed);
|
||||
|
||||
/**
|
||||
* lws_xos() - get next xoshiro256 PRNG result and update state
|
||||
*
|
||||
* \param xos: the PRNG state to use
|
||||
*
|
||||
* Returns next 64-bit PRNG result. These are cheap to get,
|
||||
* quite a white noise sequence, and completely deterministic
|
||||
* according to the seed it was initialized with.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN uint64_t LWS_WARN_UNUSED_RESULT
|
||||
lws_xos(struct lws_xos *xos);
|
||||
|
||||
/**
|
||||
* lws_xos_percent() - return 1 a given percent of the time on average
|
||||
*
|
||||
* \param xos: the PRNG state to use
|
||||
* \param percent: chance in 100 of returning 1
|
||||
*
|
||||
* Returns 1 if next random % 100 is < \p percent, such that
|
||||
* 100 always returns 1, 0 never returns 1, and the chance linearly scales
|
||||
* inbetween
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_xos_percent(struct lws_xos *xos, int percent);
|
||||
|
||||
#if defined(LWS_WITH_SYS_FAULT_INJECTION)
|
||||
|
||||
enum {
|
||||
LWSFI_ALWAYS,
|
||||
LWSFI_DETERMINISTIC, /* do .count injections after .pre then stop */
|
||||
LWSFI_PROBABILISTIC, /* .pre % chance of injection */
|
||||
LWSFI_PATTERN, /* use .count bits in .pattern after .pre */
|
||||
LWSFI_PATTERN_ALLOC, /* as _PATTERN, but .pattern is malloc'd */
|
||||
LWSFI_RANGE /* pick a number between pre and count */
|
||||
};
|
||||
|
||||
typedef struct lws_fi {
|
||||
const char *name;
|
||||
const uint8_t *pattern;
|
||||
uint64_t pre;
|
||||
uint64_t count;
|
||||
uint64_t times; /* start at 0, tracks usage */
|
||||
char type; /* LWSFI_* */
|
||||
} lws_fi_t;
|
||||
|
||||
typedef struct lws_fi_ctx {
|
||||
lws_dll2_owner_t fi_owner;
|
||||
struct lws_xos xos;
|
||||
const char *name;
|
||||
} lws_fi_ctx_t;
|
||||
|
||||
/**
|
||||
* lws_fi() - find out if we should perform the named fault injection this time
|
||||
*
|
||||
* \param fic: fault injection tracking context
|
||||
* \param fi_name: name of fault injection
|
||||
*
|
||||
* This checks if the named fault is configured in the fi tracking context
|
||||
* provided, if it is, then it will make a decision if the named fault should
|
||||
* be applied this time, using the tracking in the named lws_fi_t.
|
||||
*
|
||||
* If the provided context has a parent, that is also checked for the named fi
|
||||
* item recursively, with the first found being used to determine if to inject
|
||||
* or not.
|
||||
*
|
||||
* If LWS_WITH_SYS_FAULT_INJECTION is not defined, then this always return 0.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_fi(const lws_fi_ctx_t *fic, const char *fi_name);
|
||||
|
||||
/**
|
||||
* lws_fi_range() - get a random number from a range
|
||||
*
|
||||
* \param fic: fault injection tracking context
|
||||
* \param fi_name: name of fault injection
|
||||
* \param result: points to uint64_t to be set to the result
|
||||
*
|
||||
* This lets you get a random number from an externally-set range, set using a
|
||||
* fault injection syntax like "myfault(123..456)". That will cause us to
|
||||
* return a number between those two inclusive, from the seeded PRNG.
|
||||
*
|
||||
* This is useful when you used lws_fi() with its own fault name to decide
|
||||
* whether to inject the fault, and then the code to cause the fault needs
|
||||
* additional constrained pseudo-random fuzzing for, eg, delays before issuing
|
||||
* the fault.
|
||||
*
|
||||
* Returns 0 if \p *result is set, else nonzero for failure.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_fi_range(const lws_fi_ctx_t *fic, const char *name, uint64_t *result);
|
||||
|
||||
/**
|
||||
* lws_fi_add() - add an allocated copy of fault injection to a context
|
||||
*
|
||||
* \param fic: fault injection tracking context
|
||||
* \param fi: the fault injection details
|
||||
*
|
||||
* This allocates a copy of \p fi and attaches it to the fault injection context
|
||||
* \p fic. \p fi can go out of scope after this safely.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi);
|
||||
|
||||
/**
|
||||
* lws_fi_remove() - remove an allocated copy of fault injection from a context
|
||||
*
|
||||
* \param fic: fault injection tracking context
|
||||
* \param name: the fault injection name to remove
|
||||
*
|
||||
* This looks for the named fault injection and removes and destroys it from
|
||||
* the specified fault injection context
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fi_remove(lws_fi_ctx_t *fic, const char *name);
|
||||
|
||||
/**
|
||||
* lws_fi_import() - transfers all the faults from one context to another
|
||||
*
|
||||
* \param fic_dest: the fault context to receive the faults
|
||||
* \param fic_src: the fault context that will be emptied out into \p fic_dest
|
||||
*
|
||||
* This is used to initialize created object fault injection contexts from
|
||||
* the caller.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src);
|
||||
|
||||
/**
|
||||
* lws_fi_inherit_copy() - attach copies of matching fault injection objects to dest
|
||||
*
|
||||
* \param fic_dest: destination Fault Injection context
|
||||
* \param fic_src: parent fault context that may contain matching rules
|
||||
* \param scope: the name of the path match required, eg, "vh"
|
||||
* \param value: the dynamic name of our match, eg, "myvhost"
|
||||
*
|
||||
* If called with scope "vh" and value "myvhost", then matches faults starting
|
||||
* "vh=myvhost/", strips that part of the name if it matches and makes a copy
|
||||
* of the rule with the modified name attached to the destination Fault Injection
|
||||
* context.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fi_inherit_copy(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src,
|
||||
const char *scope, const char *value);
|
||||
|
||||
/**
|
||||
* lws_fi_destroy() - removes all allocated fault injection entries
|
||||
*
|
||||
* \param fic: fault injection tracking context
|
||||
*
|
||||
* This walks any allocated fault injection entries in \p fic and detaches and
|
||||
* destroys them. It doesn't try to destroc \p fic itself, since this is
|
||||
* not usually directly allocated.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fi_destroy(const lws_fi_ctx_t *fic);
|
||||
|
||||
/**
|
||||
* lws_fi_deserialize() - adds fault in string form to Fault Injection Context
|
||||
*
|
||||
* \p fic: the fault injection context
|
||||
* \p sers: the string serializing the desired fault details
|
||||
*
|
||||
* This turns a string like "ss=captive_portal_detect/wsi/dnsfail(10%)" into
|
||||
* a fault injection struct added to the fault injection context \p fic
|
||||
*
|
||||
* You can prepare the context creation info .fic with these before creating
|
||||
* the context, and use namespace paths on those to target other objects.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
_lws_fi_user_wsi_fi(struct lws *wsi, const char *name);
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
_lws_fi_user_context_fi(struct lws_context *ctx, const char *name);
|
||||
|
||||
#if defined(LWS_WITH_SECURE_STREAMS)
|
||||
struct lws_ss_handle;
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
_lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *name);
|
||||
#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
|
||||
struct lws_sspc_handle;
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
_lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *name);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define lws_fi_user_wsi_fi(_wsi, _name) _lws_fi_user_wsi_fi(_wsi, _name)
|
||||
#define lws_fi_user_context_fi(_ctx, _name) _lws_fi_user_context_fi(_ctx, _name)
|
||||
#define lws_fi_user_ss_fi(_h, _name) _lws_fi_user_ss_fi(_h, _name)
|
||||
#define lws_fi_user_sspc_fi(_h, _name) _lws_fi_user_sspc_fi(_h, _name)
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Helper so we can leave lws_fi() calls embedded in the code being tested,
|
||||
* if fault injection is not enabled then it just always says "no" at buildtime.
|
||||
*/
|
||||
|
||||
#define lws_fi(_fi_name, _fic) (0)
|
||||
#define lws_fi_destroy(_x)
|
||||
#define lws_fi_inherit_copy(_a, _b, _c, _d)
|
||||
#define lws_fi_deserialize(_x, _y)
|
||||
#define lws_fi_user_wsi_fi(_wsi, _name) (0)
|
||||
#define lws_fi_user_context_fi(_wsi, _name) (0)
|
||||
#define lws_fi_user_ss_fi(_h, _name) (0)
|
||||
#define lws_fi_user_sspc_fi(_h, _name) (0)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is included from libwebsockets.h if LWS_PLAT_FREERTOS
|
||||
*/
|
||||
|
||||
typedef int lws_sockfd_type;
|
||||
typedef int lws_filefd_type;
|
||||
|
||||
#if defined(LWS_AMAZON_RTOS)
|
||||
#include <FreeRTOS.h>
|
||||
#include <event_groups.h>
|
||||
#include <string.h>
|
||||
#include "timers.h"
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
/*
|
||||
* Later lwip (at least 2.1.12) already defines these in its own headers
|
||||
* protected by the same test as used here... if POLLIN / POLLOUT already exist
|
||||
* then assume no need to declare those and struct pollfd.
|
||||
*
|
||||
* Older lwip needs these declarations done here.
|
||||
*/
|
||||
|
||||
#if !defined(POLLIN) && !defined(POLLOUT)
|
||||
|
||||
struct pollfd {
|
||||
lws_sockfd_type fd; /**< fd related to */
|
||||
short events; /**< which POLL... events to respond to */
|
||||
short revents; /**< which POLL... events occurred */
|
||||
};
|
||||
#define POLLIN 0x0001
|
||||
#define POLLPRI 0x0002
|
||||
#define POLLOUT 0x0004
|
||||
#define POLLERR 0x0008
|
||||
#define POLLHUP 0x0010
|
||||
#define POLLNVAL 0x0020
|
||||
|
||||
#endif
|
||||
|
||||
#else /* LWS_AMAZON_RTOS */
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/event_groups.h>
|
||||
#include <string.h>
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
//#include "esp_event_loop.h"
|
||||
#include "nvs.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "freertos/timers.h"
|
||||
|
||||
#if defined(LWS_ESP_PLATFORM)
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/netdb.h"
|
||||
#if defined(LWS_WITH_DRIVERS)
|
||||
#include "libwebsockets/lws-gpio.h"
|
||||
extern const lws_gpio_ops_t lws_gpio_plat;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* LWS_AMAZON_RTOS */
|
||||
|
||||
#if !defined(CONFIG_FREERTOS_HZ)
|
||||
#define CONFIG_FREERTOS_HZ 100
|
||||
#endif
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup search Search
|
||||
*
|
||||
* ##Full-text search
|
||||
*
|
||||
* Lws provides superfast indexing and fulltext searching from index files on
|
||||
* storage.
|
||||
*/
|
||||
///@{
|
||||
|
||||
struct lws_fts;
|
||||
struct lws_fts_file;
|
||||
|
||||
/*
|
||||
* Queries produce their results in an lwsac, using these public API types.
|
||||
* The first thing in the lwsac is always a struct lws_fts_result (see below)
|
||||
* containing heads for linked-lists of the other result types.
|
||||
*/
|
||||
|
||||
/* one filepath's results */
|
||||
|
||||
struct lws_fts_result_filepath {
|
||||
struct lws_fts_result_filepath *next;
|
||||
int matches; /* logical number of matches */
|
||||
int matches_length; /* bytes in length table (may be zero) */
|
||||
int lines_in_file;
|
||||
int filepath_length;
|
||||
|
||||
/* - uint32_t line table follows (first for alignment) */
|
||||
/* - filepath (of filepath_length) follows */
|
||||
};
|
||||
|
||||
/* autocomplete result */
|
||||
|
||||
struct lws_fts_result_autocomplete {
|
||||
struct lws_fts_result_autocomplete *next;
|
||||
int instances;
|
||||
int agg_instances;
|
||||
int ac_length;
|
||||
char elided; /* children skipped in interest of antecedent children */
|
||||
char has_children;
|
||||
|
||||
/* - autocomplete suggestion (of length ac_length) follows */
|
||||
};
|
||||
|
||||
/*
|
||||
* The results lwsac always starts with this. If no results and / or no
|
||||
* autocomplete the members may be NULL. This implies the symbol nor any
|
||||
* suffix on it exists in the trie file.
|
||||
*/
|
||||
struct lws_fts_result {
|
||||
struct lws_fts_result_filepath *filepath_head;
|
||||
struct lws_fts_result_autocomplete *autocomplete_head;
|
||||
int duration_ms;
|
||||
int effective_flags; /* the search flags that were used */
|
||||
};
|
||||
|
||||
/*
|
||||
* index creation functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* lws_fts_create() - Create a new index file
|
||||
*
|
||||
* \param fd: The fd opened for write
|
||||
*
|
||||
* Inits a new index file, returning a struct lws_fts to represent it
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_fts *
|
||||
lws_fts_create(int fd);
|
||||
|
||||
/**
|
||||
* lws_fts_destroy() - Finalize a new index file / destroy the trie lwsac
|
||||
*
|
||||
* \param trie: The previously opened index being finalized
|
||||
*
|
||||
* Finalizes an index file that was being created, and frees the memory involved
|
||||
* *trie is set to NULL afterwards.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fts_destroy(struct lws_fts **trie);
|
||||
|
||||
/**
|
||||
* lws_fts_file_index() - Create a new entry in the trie file for an input path
|
||||
*
|
||||
* \param t: The previously opened index being written
|
||||
* \param filepath: The filepath (which may be virtual) associated with this file
|
||||
* \param filepath_len: The number of chars in the filepath
|
||||
* \param priority: not used yet
|
||||
*
|
||||
* Returns an ordinal that represents this new filepath in the index file.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_fts_file_index(struct lws_fts *t, const char *filepath, int filepath_len,
|
||||
int priority);
|
||||
|
||||
/**
|
||||
* lws_fts_fill() - Process all or a bufferload of input file
|
||||
*
|
||||
* \param t: The previously opened index being written
|
||||
* \param file_index: The ordinal representing this input filepath
|
||||
* \param buf: A bufferload of data from the input file
|
||||
* \param len: The number of bytes in buf
|
||||
*
|
||||
* Indexes a buffer of data from the input file.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_fts_fill(struct lws_fts *t, uint32_t file_index, const char *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* lws_fts_serialize() - Store the in-memory trie into the index file
|
||||
*
|
||||
* \param t: The previously opened index being written
|
||||
*
|
||||
* The trie is held in memory where it can be added to... after all the input
|
||||
* filepaths and data have been processed, this is called to serialize /
|
||||
* write the trie data into the index file.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_fts_serialize(struct lws_fts *t);
|
||||
|
||||
/*
|
||||
* index search functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* lws_fts_open() - Open an existing index file to search it
|
||||
*
|
||||
* \param filepath: The filepath to the index file to open
|
||||
*
|
||||
* Opening the index file returns an opaque struct lws_fts_file * that is
|
||||
* used to perform other operations on it, or NULL if it can't be opened.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_fts_file *
|
||||
lws_fts_open(const char *filepath);
|
||||
|
||||
#define LWSFTS_F_QUERY_AUTOCOMPLETE (1 << 0)
|
||||
#define LWSFTS_F_QUERY_FILES (1 << 1)
|
||||
#define LWSFTS_F_QUERY_FILE_LINES (1 << 2)
|
||||
#define LWSFTS_F_QUERY_QUOTE_LINE (1 << 3)
|
||||
|
||||
struct lws_fts_search_params {
|
||||
/* the actual search term */
|
||||
const char *needle;
|
||||
/* if non-NULL, FILE results for this filepath only */
|
||||
const char *only_filepath;
|
||||
/* will be set to the results lwsac */
|
||||
struct lwsac *results_head;
|
||||
/* combination of LWSFTS_F_QUERY_* flags */
|
||||
int flags;
|
||||
/* maximum number of autocomplete suggestions to return */
|
||||
int max_autocomplete;
|
||||
/* maximum number of filepaths to return */
|
||||
int max_files;
|
||||
/* maximum number of line number results to return per filepath */
|
||||
int max_lines;
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_fts_search() - Perform a search operation on an index
|
||||
*
|
||||
* \param jtf: The index file struct returned by lws_fts_open
|
||||
* \param ftsp: The struct lws_fts_search_params filled in by the caller
|
||||
*
|
||||
* The caller should memset the ftsp struct to 0 to ensure members that may be
|
||||
* introduced in later versions contain known values, then set the related
|
||||
* members to describe the kind of search action required.
|
||||
*
|
||||
* ftsp->results_head is the results lwsac, or NULL. It should be freed with
|
||||
* lwsac_free() when the results are finished with.
|
||||
*
|
||||
* Returns a pointer into the results lwsac that is a struct lws_fts_result
|
||||
* containing the head pointers into linked-lists of results for autocomplete
|
||||
* and filepath data, along with some sundry information. This does not need
|
||||
* to be freed since freeing the lwsac will also remove this and everything it
|
||||
* points to.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_fts_result *
|
||||
lws_fts_search(struct lws_fts_file *jtf, struct lws_fts_search_params *ftsp);
|
||||
|
||||
/**
|
||||
* lws_fts_close() - Close a previously-opened index file
|
||||
*
|
||||
* \param jtf: The pointer returned from the open
|
||||
*
|
||||
* Closes the file handle on the index and frees any allocations
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_fts_close(struct lws_fts_file *jtf);
|
||||
|
||||
///@}
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup generic AES
|
||||
* ## Generic AES related functions
|
||||
*
|
||||
* Lws provides generic AES functions that abstract the ones
|
||||
* provided by whatever tls library you are linking against.
|
||||
*
|
||||
* It lets you use the same code if you build against mbedtls or OpenSSL
|
||||
* for example.
|
||||
*/
|
||||
///@{
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/gcm.h>
|
||||
#endif
|
||||
|
||||
enum enum_aes_modes {
|
||||
LWS_GAESM_CBC,
|
||||
LWS_GAESM_CFB128,
|
||||
LWS_GAESM_CFB8,
|
||||
LWS_GAESM_CTR,
|
||||
LWS_GAESM_ECB,
|
||||
LWS_GAESM_OFB,
|
||||
LWS_GAESM_XTS, /* care... requires double-length key */
|
||||
LWS_GAESM_GCM,
|
||||
LWS_GAESM_KW,
|
||||
};
|
||||
|
||||
enum enum_aes_operation {
|
||||
LWS_GAESO_ENC,
|
||||
LWS_GAESO_DEC
|
||||
};
|
||||
|
||||
enum enum_aes_padding {
|
||||
LWS_GAESP_NO_PADDING,
|
||||
LWS_GAESP_WITH_PADDING
|
||||
};
|
||||
|
||||
/* include/libwebsockets/lws-jwk.h must be included before this */
|
||||
|
||||
#define LWS_AES_BLOCKSIZE 128
|
||||
#define LWS_AES_CBC_BLOCKLEN 16
|
||||
|
||||
struct lws_genaes_ctx {
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
union {
|
||||
mbedtls_aes_context ctx;
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
mbedtls_aes_xts_context ctx_xts;
|
||||
#endif
|
||||
mbedtls_gcm_context ctx_gcm;
|
||||
} u;
|
||||
#else
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const EVP_CIPHER *cipher;
|
||||
ENGINE *engine;
|
||||
char init;
|
||||
#endif
|
||||
unsigned char tag[16];
|
||||
struct lws_gencrypto_keyelem *k;
|
||||
enum enum_aes_operation op;
|
||||
enum enum_aes_modes mode;
|
||||
enum enum_aes_padding padding;
|
||||
int taglen;
|
||||
char underway;
|
||||
};
|
||||
|
||||
/** lws_genaes_create() - Create RSA public decrypt context
|
||||
*
|
||||
* \param ctx: your struct lws_genaes_ctx
|
||||
* \param op: LWS_GAESO_ENC or LWS_GAESO_DEC
|
||||
* \param mode: one of LWS_GAESM_
|
||||
* \param el: struct prepared with key element data
|
||||
* \param padding: 0 = no padding, 1 = padding
|
||||
* \param engine: if openssl engine used, pass the pointer here
|
||||
*
|
||||
* Creates an RSA context with a public key associated with it, formed from
|
||||
* the key elements in \p el.
|
||||
*
|
||||
* Returns 0 for OK or nonzero for error.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genaes_create(struct lws_genaes_ctx *ctx, enum enum_aes_operation op,
|
||||
enum enum_aes_modes mode, struct lws_gencrypto_keyelem *el,
|
||||
enum enum_aes_padding padding, void *engine);
|
||||
|
||||
/** lws_genaes_destroy() - Destroy genaes AES context
|
||||
*
|
||||
* \param ctx: your struct lws_genaes_ctx
|
||||
* \param tag: NULL, or, GCM-only: buffer to receive tag
|
||||
* \param tlen: 0, or, GCM-only: length of tag buffer
|
||||
*
|
||||
* Destroys any allocations related to \p ctx.
|
||||
*
|
||||
* For GCM only, up to tlen bytes of tag buffer will be set on exit.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genaes_destroy(struct lws_genaes_ctx *ctx, unsigned char *tag, size_t tlen);
|
||||
|
||||
/** lws_genaes_crypt() - Encrypt or decrypt
|
||||
*
|
||||
* \param ctx: your struct lws_genaes_ctx
|
||||
* \param in: input plaintext or ciphertext
|
||||
* \param len: length of input (which is always length of output)
|
||||
* \param out: output plaintext or ciphertext
|
||||
* \param iv_or_nonce_ctr_or_data_unit_16: NULL, iv, nonce_ctr16, or data_unit16
|
||||
* \param stream_block_16: pointer to 16-byte stream block for CTR mode only
|
||||
* \param nc_or_iv_off: NULL or pointer to nc, or iv_off
|
||||
* \param taglen: length of tag
|
||||
*
|
||||
* Encrypts or decrypts using the AES mode set when the ctx was created.
|
||||
* The last three arguments have different meanings depending on the mode:
|
||||
*
|
||||
* KW CBC CFB128 CFB8 CTR ECB OFB XTS
|
||||
* iv_or_nonce_ct.._unit_16 : iv iv iv iv nonce NULL iv dataunt
|
||||
* stream_block_16 : NULL NULL NULL NULL stream NULL NULL NULL
|
||||
* nc_or_iv_off : NULL NULL iv_off NULL nc_off NULL iv_off NULL
|
||||
*
|
||||
* For GCM:
|
||||
*
|
||||
* iv_or_nonce_ctr_or_data_unit_16 : iv
|
||||
* stream_block_16 : pointer to tag
|
||||
* nc_or_iv_off : set pointed-to size_t to iv length
|
||||
* in : first call: additional data, subsequently
|
||||
* : input data
|
||||
* len : first call: add data length, subsequently
|
||||
* : input / output length
|
||||
*
|
||||
* The length of the optional arg is always 16 if used, regardless of the mode.
|
||||
*
|
||||
* Returns 0 for OK or nonzero for error.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genaes_crypt(struct lws_genaes_ctx *ctx, const uint8_t *in, size_t len,
|
||||
uint8_t *out,
|
||||
uint8_t *iv_or_nonce_ctr_or_data_unit_16,
|
||||
uint8_t *stream_block_16,
|
||||
size_t *nc_or_iv_off, int taglen);
|
||||
|
||||
///@}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These are gencrypto-level constants... they are used by both JOSE and direct
|
||||
* gencrypto code. However while JWK relies on these, using gencrypto apis has
|
||||
* no dependency at all on any JOSE type.
|
||||
*/
|
||||
|
||||
enum lws_gencrypto_kty {
|
||||
LWS_GENCRYPTO_KTY_UNKNOWN,
|
||||
|
||||
LWS_GENCRYPTO_KTY_OCT,
|
||||
LWS_GENCRYPTO_KTY_RSA,
|
||||
LWS_GENCRYPTO_KTY_EC
|
||||
};
|
||||
|
||||
/*
|
||||
* Keytypes where the same element name is reused must all agree to put the
|
||||
* same-named element at the same e[] index. It's because when used with jwk,
|
||||
* we parse and store in incoming key data, but we may not be informed of the
|
||||
* definitive keytype until the end.
|
||||
*/
|
||||
|
||||
enum lws_gencrypto_oct_tok {
|
||||
LWS_GENCRYPTO_OCT_KEYEL_K, /* note... same offset as AES K */
|
||||
|
||||
LWS_GENCRYPTO_OCT_KEYEL_COUNT
|
||||
};
|
||||
|
||||
enum lws_gencrypto_rsa_tok {
|
||||
LWS_GENCRYPTO_RSA_KEYEL_E,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_N,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_D, /* note... same offset as EC D */
|
||||
LWS_GENCRYPTO_RSA_KEYEL_P,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_Q,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_DP,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_DQ,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_QI,
|
||||
|
||||
/* we don't actively use these if given, but may come from COSE */
|
||||
|
||||
LWS_GENCRYPTO_RSA_KEYEL_OTHER,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_RI,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_DI,
|
||||
LWS_GENCRYPTO_RSA_KEYEL_TI,
|
||||
|
||||
LWS_GENCRYPTO_RSA_KEYEL_COUNT
|
||||
};
|
||||
|
||||
enum lws_gencrypto_ec_tok {
|
||||
LWS_GENCRYPTO_EC_KEYEL_CRV,
|
||||
LWS_GENCRYPTO_EC_KEYEL_X,
|
||||
/* note... same offset as RSA D */
|
||||
LWS_GENCRYPTO_EC_KEYEL_D = LWS_GENCRYPTO_RSA_KEYEL_D,
|
||||
LWS_GENCRYPTO_EC_KEYEL_Y,
|
||||
|
||||
LWS_GENCRYPTO_EC_KEYEL_COUNT
|
||||
};
|
||||
|
||||
enum lws_gencrypto_aes_tok {
|
||||
/* note... same offset as OCT K */
|
||||
LWS_GENCRYPTO_AES_KEYEL_K = LWS_GENCRYPTO_OCT_KEYEL_K,
|
||||
|
||||
LWS_GENCRYPTO_AES_KEYEL_COUNT
|
||||
};
|
||||
|
||||
/* largest number of key elements for any algorithm */
|
||||
#define LWS_GENCRYPTO_MAX_KEYEL_COUNT LWS_GENCRYPTO_RSA_KEYEL_COUNT
|
||||
|
||||
/* this "stretchy" type holds individual key element data in binary form.
|
||||
* It's typcially used in an array with the layout mapping the element index to
|
||||
* the key element meaning defined by the enums above. An array of these of
|
||||
* length LWS_GENCRYPTO_MAX_KEYEL_COUNT can define key elements for any key
|
||||
* type.
|
||||
*/
|
||||
|
||||
typedef struct lws_gencrypto_keyelem {
|
||||
uint8_t *buf;
|
||||
uint32_t len;
|
||||
} lws_gc_elem_t;
|
||||
|
||||
|
||||
/**
|
||||
* lws_gencrypto_bits_to_bytes() - returns rounded up bytes needed for bits
|
||||
*
|
||||
* \param bits
|
||||
*
|
||||
* Returns the number of bytes needed to store the given number of bits. If
|
||||
* a byte is partially used, the byte count is rounded up.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_gencrypto_bits_to_bytes(int bits);
|
||||
|
||||
/**
|
||||
* lws_base64_size() - returns estimated size of base64 encoding
|
||||
*
|
||||
* \param bytes
|
||||
*
|
||||
* Returns a slightly oversize estimate of the size of a base64 encoded version
|
||||
* of the given amount of unencoded data.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_base64_size(int bytes);
|
||||
|
||||
/**
|
||||
* lws_gencrypto_padded_length() - returns PKCS#5/#7 padded length
|
||||
*
|
||||
* @param blocksize - blocksize to pad to
|
||||
* @param len - Length of input to pad
|
||||
*
|
||||
* Returns the length of a buffer originally of size len after PKCS#5 or PKCS#7
|
||||
* padding has been applied to it.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lws_gencrypto_padded_length(size_t block_size, size_t len);
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
enum enum_genec_alg {
|
||||
LEGENEC_UNKNOWN,
|
||||
|
||||
LEGENEC_ECDH,
|
||||
LEGENEC_ECDSA
|
||||
};
|
||||
|
||||
struct lws_genec_ctx {
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
union {
|
||||
mbedtls_ecdh_context *ctx_ecdh;
|
||||
mbedtls_ecdsa_context *ctx_ecdsa;
|
||||
} u;
|
||||
#else
|
||||
EVP_PKEY_CTX *ctx[2];
|
||||
#endif
|
||||
struct lws_context *context;
|
||||
const struct lws_ec_curves *curve_table;
|
||||
enum enum_genec_alg genec_alg;
|
||||
|
||||
char has_private;
|
||||
};
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
enum enum_lws_dh_side {
|
||||
LDHS_OURS = MBEDTLS_ECDH_OURS,
|
||||
LDHS_THEIRS = MBEDTLS_ECDH_THEIRS
|
||||
};
|
||||
#else
|
||||
enum enum_lws_dh_side {
|
||||
LDHS_OURS,
|
||||
LDHS_THEIRS
|
||||
};
|
||||
#endif
|
||||
|
||||
struct lws_ec_curves {
|
||||
const char *name;
|
||||
int tls_lib_nid;
|
||||
uint16_t key_bytes;
|
||||
};
|
||||
|
||||
|
||||
/* ECDH-specific apis */
|
||||
|
||||
/** lws_genecdh_create() - Create a genecdh
|
||||
*
|
||||
* \param ctx: your genec context
|
||||
* \param context: your lws_context (for RNG access)
|
||||
* \param curve_table: NULL, enabling P-256, P-384 and P-521, or a replacement
|
||||
* struct lws_ec_curves array, terminated by an entry with
|
||||
* .name = NULL, of curves you want to allow
|
||||
*
|
||||
* Initializes a genecdh
|
||||
*/
|
||||
LWS_VISIBLE int
|
||||
lws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context,
|
||||
const struct lws_ec_curves *curve_table);
|
||||
|
||||
/** lws_genecdh_set_key() - Apply an EC key to our or theirs side
|
||||
*
|
||||
* \param ctx: your genecdh context
|
||||
* \param el: your key elements
|
||||
* \param side: LDHS_OURS or LDHS_THEIRS
|
||||
*
|
||||
* Applies an EC key to one side or the other of an ECDH ctx
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el,
|
||||
enum enum_lws_dh_side side);
|
||||
|
||||
/** lws_genecdh_new_keypair() - Create a genec with a new public / private key
|
||||
*
|
||||
* \param ctx: your genec context
|
||||
* \param side: LDHS_OURS or LDHS_THEIRS
|
||||
* \param curve_name: an EC curve name, like "P-256"
|
||||
* \param el: array pf LWS_GENCRYPTO_EC_KEYEL_COUNT key elems to take the new key
|
||||
*
|
||||
* Creates a genecdh with a newly minted EC public / private key
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
|
||||
const char *curve_name, struct lws_gencrypto_keyelem *el);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss,
|
||||
int *ss_len);
|
||||
|
||||
|
||||
/* ECDSA-specific apis */
|
||||
|
||||
/** lws_genecdsa_create() - Create a genecdsa and
|
||||
*
|
||||
* \param ctx: your genec context
|
||||
* \param context: your lws_context (for RNG access)
|
||||
* \param curve_table: NULL, enabling P-256, P-384 and P-521, or a replacement
|
||||
* struct lws_ec_curves array, terminated by an entry with
|
||||
* .name = NULL, of curves you want to allow
|
||||
*
|
||||
* Initializes a genecdh
|
||||
*/
|
||||
LWS_VISIBLE int
|
||||
lws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context,
|
||||
const struct lws_ec_curves *curve_table);
|
||||
|
||||
/** lws_genecdsa_new_keypair() - Create a genecdsa with a new public / private key
|
||||
*
|
||||
* \param ctx: your genec context
|
||||
* \param curve_name: an EC curve name, like "P-256"
|
||||
* \param el: array pf LWS_GENCRYPTO_EC_KEYEL_COUNT key elements to take the new key
|
||||
*
|
||||
* Creates a genecdsa with a newly minted EC public / private key
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name,
|
||||
struct lws_gencrypto_keyelem *el);
|
||||
|
||||
/** lws_genecdsa_set_key() - Apply an EC key to an ecdsa context
|
||||
*
|
||||
* \param ctx: your genecdsa context
|
||||
* \param el: your key elements
|
||||
*
|
||||
* Applies an EC key to an ecdsa context
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdsa_set_key(struct lws_genec_ctx *ctx,
|
||||
const struct lws_gencrypto_keyelem *el);
|
||||
|
||||
/** lws_genecdsa_hash_sig_verify_jws() - Verifies a JWS ECDSA signature on a given hash
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: unencrypted payload (usually a recomputed hash)
|
||||
* \param hash_type: one of LWS_GENHASH_TYPE_
|
||||
* \param keybits: number of bits in the crypto key
|
||||
* \param sig: pointer to the signature we received with the payload
|
||||
* \param sig_len: length of the signature we are checking in bytes
|
||||
*
|
||||
* This just looks at the signed hash... that's why there's no input length
|
||||
* parameter, it's decided by the choice of hash. It's up to you to confirm
|
||||
* separately the actual payload matches the hash that was confirmed by this to
|
||||
* be validly signed.
|
||||
*
|
||||
* Returns <0 for error, or 0 if signature matches the hash + key..
|
||||
*
|
||||
* The JWS ECDSA signature verification algorithm differs to generic ECDSA
|
||||
* signatures and they're not interoperable.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
|
||||
enum lws_genhash_types hash_type, int keybits,
|
||||
const uint8_t *sig, size_t sig_len);
|
||||
|
||||
/** lws_genecdsa_hash_sign_jws() - Creates a JWS ECDSA signature for a hash you provide
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: precomputed hash
|
||||
* \param hash_type: one of LWS_GENHASH_TYPE_
|
||||
* \param keybits: number of bits in the crypto key
|
||||
* \param sig: pointer to buffer to take signature
|
||||
* \param sig_len: length of the buffer (must be >= length of key N)
|
||||
*
|
||||
* Returns <0 for error, or 0 for success.
|
||||
*
|
||||
* This creates a JWS ECDSA signature for a hash you already computed and provide.
|
||||
*
|
||||
* The JWS ECDSA signature generation algorithm differs to generic ECDSA
|
||||
* signatures and they're not interoperable.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
|
||||
enum lws_genhash_types hash_type, int keybits,
|
||||
uint8_t *sig, size_t sig_len);
|
||||
|
||||
|
||||
/* Apis that apply to both ECDH and ECDSA */
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_genec_destroy(struct lws_genec_ctx *ctx);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_genec_destroy_elements(struct lws_gencrypto_keyelem *el);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genec_dump(struct lws_gencrypto_keyelem *el);
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup generichash Generic Hash
|
||||
* ## Generic Hash related functions
|
||||
*
|
||||
* Lws provides generic hash / digest accessors that abstract the ones
|
||||
* provided by whatever tls library you are linking against.
|
||||
*
|
||||
* It lets you use the same code if you build against mbedtls or OpenSSL
|
||||
* for example.
|
||||
*/
|
||||
///@{
|
||||
|
||||
enum lws_genhash_types {
|
||||
LWS_GENHASH_TYPE_UNKNOWN,
|
||||
LWS_GENHASH_TYPE_MD5,
|
||||
LWS_GENHASH_TYPE_SHA1,
|
||||
LWS_GENHASH_TYPE_SHA256,
|
||||
LWS_GENHASH_TYPE_SHA384,
|
||||
LWS_GENHASH_TYPE_SHA512,
|
||||
};
|
||||
|
||||
enum lws_genhmac_types {
|
||||
LWS_GENHMAC_TYPE_UNKNOWN,
|
||||
LWS_GENHMAC_TYPE_SHA256,
|
||||
LWS_GENHMAC_TYPE_SHA384,
|
||||
LWS_GENHMAC_TYPE_SHA512,
|
||||
};
|
||||
|
||||
#define LWS_GENHASH_LARGEST 64
|
||||
|
||||
struct lws_genhash_ctx {
|
||||
uint8_t type;
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
union {
|
||||
mbedtls_md5_context md5;
|
||||
mbedtls_sha1_context sha1;
|
||||
mbedtls_sha256_context sha256;
|
||||
mbedtls_sha512_context sha512; /* 384 also uses this */
|
||||
const mbedtls_md_info_t *hmac;
|
||||
} u;
|
||||
#else
|
||||
const EVP_MD *evp_type;
|
||||
EVP_MD_CTX *mdctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct lws_genhmac_ctx {
|
||||
uint8_t type;
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
const mbedtls_md_info_t *hmac;
|
||||
mbedtls_md_context_t ctx;
|
||||
#else
|
||||
const EVP_MD *evp_type;
|
||||
|
||||
#if defined(LWS_HAVE_EVP_PKEY_new_raw_private_key)
|
||||
EVP_MD_CTX *ctx;
|
||||
EVP_PKEY *key;
|
||||
#else
|
||||
#if defined(LWS_HAVE_HMAC_CTX_new)
|
||||
HMAC_CTX *ctx;
|
||||
#else
|
||||
HMAC_CTX ctx;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
/** lws_genhash_size() - get hash size in bytes
|
||||
*
|
||||
* \param type: one of LWS_GENHASH_TYPE_...
|
||||
*
|
||||
* Returns number of bytes in this type of hash
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT
|
||||
lws_genhash_size(enum lws_genhash_types type);
|
||||
|
||||
/** lws_genhmac_size() - get hash size in bytes
|
||||
*
|
||||
* \param type: one of LWS_GENHASH_TYPE_...
|
||||
*
|
||||
* Returns number of bytes in this type of hmac
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT
|
||||
lws_genhmac_size(enum lws_genhmac_types type);
|
||||
|
||||
/** lws_genhash_init() - prepare your struct lws_genhash_ctx for use
|
||||
*
|
||||
* \param ctx: your struct lws_genhash_ctx
|
||||
* \param type: one of LWS_GENHASH_TYPE_...
|
||||
*
|
||||
* Initializes the hash context for the type you requested
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type);
|
||||
|
||||
/** lws_genhash_update() - digest len bytes of the buffer starting at in
|
||||
*
|
||||
* \param ctx: your struct lws_genhash_ctx
|
||||
* \param in: start of the bytes to digest
|
||||
* \param len: count of bytes to digest
|
||||
*
|
||||
* Updates the state of your hash context to reflect digesting len bytes from in
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len);
|
||||
|
||||
/** lws_genhash_destroy() - copy out the result digest and destroy the ctx
|
||||
*
|
||||
* \param ctx: your struct lws_genhash_ctx
|
||||
* \param result: NULL, or where to copy the result hash
|
||||
*
|
||||
* Finalizes the hash and copies out the digest. Destroys any allocations such
|
||||
* that ctx can safely go out of scope after calling this.
|
||||
*
|
||||
* NULL result is supported so that you can destroy the ctx cleanly on error
|
||||
* conditions, where there is no valid result.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result);
|
||||
|
||||
/** lws_genhmac_init() - prepare your struct lws_genhmac_ctx for use
|
||||
*
|
||||
* \param ctx: your struct lws_genhmac_ctx
|
||||
* \param type: one of LWS_GENHMAC_TYPE_...
|
||||
* \param key: pointer to the start of the HMAC key
|
||||
* \param key_len: length of the HMAC key
|
||||
*
|
||||
* Initializes the hash context for the type you requested
|
||||
*
|
||||
* If the return is nonzero, it failed and there is nothing needing to be
|
||||
* destroyed.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
|
||||
const uint8_t *key, size_t key_len);
|
||||
|
||||
/** lws_genhmac_update() - digest len bytes of the buffer starting at in
|
||||
*
|
||||
* \param ctx: your struct lws_genhmac_ctx
|
||||
* \param in: start of the bytes to digest
|
||||
* \param len: count of bytes to digest
|
||||
*
|
||||
* Updates the state of your hash context to reflect digesting len bytes from in
|
||||
*
|
||||
* If the return is nonzero, it failed and needs destroying.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
|
||||
lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len);
|
||||
|
||||
/** lws_genhmac_destroy() - copy out the result digest and destroy the ctx
|
||||
*
|
||||
* \param ctx: your struct lws_genhmac_ctx
|
||||
* \param result: NULL, or where to copy the result hash
|
||||
*
|
||||
* Finalizes the hash and copies out the digest. Destroys any allocations such
|
||||
* that ctx can safely go out of scope after calling this.
|
||||
*
|
||||
* NULL result is supported so that you can destroy the ctx cleanly on error
|
||||
* conditions, where there is no valid result.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result);
|
||||
///@}
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup genericRSA Generic RSA
|
||||
* ## Generic RSA related functions
|
||||
*
|
||||
* Lws provides generic RSA functions that abstract the ones
|
||||
* provided by whatever OpenSSL library you are linking against.
|
||||
*
|
||||
* It lets you use the same code if you build against mbedtls or OpenSSL
|
||||
* for example.
|
||||
*/
|
||||
///@{
|
||||
|
||||
/* include/libwebsockets/lws-jwk.h must be included before this */
|
||||
|
||||
enum enum_genrsa_mode {
|
||||
LGRSAM_PKCS1_1_5,
|
||||
LGRSAM_PKCS1_OAEP_PSS,
|
||||
|
||||
LGRSAM_COUNT
|
||||
};
|
||||
|
||||
struct lws_genrsa_ctx {
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
mbedtls_rsa_context *ctx;
|
||||
#else
|
||||
BIGNUM *bn[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
|
||||
EVP_PKEY_CTX *ctx;
|
||||
RSA *rsa;
|
||||
#endif
|
||||
struct lws_context *context;
|
||||
enum enum_genrsa_mode mode;
|
||||
};
|
||||
|
||||
/** lws_genrsa_public_decrypt_create() - Create RSA public decrypt context
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param el: struct prepared with key element data
|
||||
* \param context: lws_context for RNG
|
||||
* \param mode: RSA mode, one of LGRSAM_ constants
|
||||
* \param oaep_hashid: the lws genhash id for the hash used in MFG1 hash
|
||||
* used in OAEP mode - normally, SHA1
|
||||
*
|
||||
* Creates an RSA context with a public key associated with it, formed from
|
||||
* the key elements in \p el.
|
||||
*
|
||||
* Mode LGRSAM_PKCS1_1_5 is in widespread use but has weaknesses. It's
|
||||
* recommended to use LGRSAM_PKCS1_OAEP_PSS for new implementations.
|
||||
*
|
||||
* Returns 0 for OK or nonzero for error.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_create(struct lws_genrsa_ctx *ctx,
|
||||
const struct lws_gencrypto_keyelem *el,
|
||||
struct lws_context *context, enum enum_genrsa_mode mode,
|
||||
enum lws_genhash_types oaep_hashid);
|
||||
|
||||
/** lws_genrsa_destroy_elements() - Free allocations in genrsa_elements
|
||||
*
|
||||
* \param el: your struct lws_gencrypto_keyelem
|
||||
*
|
||||
* This is a helper for user code making use of struct lws_gencrypto_keyelem
|
||||
* where the elements are allocated on the heap, it frees any non-NULL
|
||||
* buf element and sets the buf to NULL.
|
||||
*
|
||||
* NB: lws_genrsa_public_... apis do not need this as they take care of the key
|
||||
* creation and destruction themselves.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_genrsa_destroy_elements(struct lws_gencrypto_keyelem *el);
|
||||
|
||||
/** lws_genrsa_new_keypair() - Create new RSA keypair
|
||||
*
|
||||
* \param context: your struct lws_context (may be used for RNG)
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param mode: RSA mode, one of LGRSAM_ constants
|
||||
* \param el: struct to get the new key element data allocated into it
|
||||
* \param bits: key size, eg, 4096
|
||||
*
|
||||
* Creates a new RSA context and generates a new keypair into it, with \p bits
|
||||
* bits.
|
||||
*
|
||||
* Returns 0 for OK or nonzero for error.
|
||||
*
|
||||
* Mode LGRSAM_PKCS1_1_5 is in widespread use but has weaknesses. It's
|
||||
* recommended to use LGRSAM_PKCS1_OAEP_PSS for new implementations.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx,
|
||||
enum enum_genrsa_mode mode, struct lws_gencrypto_keyelem *el,
|
||||
int bits);
|
||||
|
||||
/** lws_genrsa_public_encrypt() - Perform RSA public key encryption
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: plaintext input
|
||||
* \param in_len: length of plaintext input
|
||||
* \param out: encrypted output
|
||||
*
|
||||
* Performs PKCS1 v1.5 Encryption
|
||||
*
|
||||
* Returns <0 for error, or length of decrypted data.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
|
||||
size_t in_len, uint8_t *out);
|
||||
|
||||
/** lws_genrsa_private_encrypt() - Perform RSA private key encryption
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: plaintext input
|
||||
* \param in_len: length of plaintext input
|
||||
* \param out: encrypted output
|
||||
*
|
||||
* Performs PKCS1 v1.5 Encryption
|
||||
*
|
||||
* Returns <0 for error, or length of decrypted data.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
|
||||
size_t in_len, uint8_t *out);
|
||||
|
||||
/** lws_genrsa_public_decrypt() - Perform RSA public key decryption
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: encrypted input
|
||||
* \param in_len: length of encrypted input
|
||||
* \param out: decrypted output
|
||||
* \param out_max: size of output buffer
|
||||
*
|
||||
* Performs PKCS1 v1.5 Decryption
|
||||
*
|
||||
* Returns <0 for error, or length of decrypted data.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
|
||||
size_t in_len, uint8_t *out, size_t out_max);
|
||||
|
||||
/** lws_genrsa_private_decrypt() - Perform RSA private key decryption
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: encrypted input
|
||||
* \param in_len: length of encrypted input
|
||||
* \param out: decrypted output
|
||||
* \param out_max: size of output buffer
|
||||
*
|
||||
* Performs PKCS1 v1.5 Decryption
|
||||
*
|
||||
* Returns <0 for error, or length of decrypted data.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
|
||||
size_t in_len, uint8_t *out, size_t out_max);
|
||||
|
||||
/** lws_genrsa_hash_sig_verify() - Verifies RSA signature on a given hash
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: input to be hashed
|
||||
* \param hash_type: one of LWS_GENHASH_TYPE_
|
||||
* \param sig: pointer to the signature we received with the payload
|
||||
* \param sig_len: length of the signature we are checking in bytes
|
||||
*
|
||||
* Returns <0 for error, or 0 if signature matches the payload + key.
|
||||
*
|
||||
* This just looks at a hash... that's why there's no input length
|
||||
* parameter, it's decided by the choice of hash. It's up to you to confirm
|
||||
* separately the actual payload matches the hash that was confirmed by this to
|
||||
* be validly signed.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in,
|
||||
enum lws_genhash_types hash_type,
|
||||
const uint8_t *sig, size_t sig_len);
|
||||
|
||||
/** lws_genrsa_hash_sign() - Creates an ECDSA signature for a hash you provide
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param in: input to be hashed and signed
|
||||
* \param hash_type: one of LWS_GENHASH_TYPE_
|
||||
* \param sig: pointer to buffer to take signature
|
||||
* \param sig_len: length of the buffer (must be >= length of key N)
|
||||
*
|
||||
* Returns <0 for error, or 0 for success.
|
||||
*
|
||||
* This creates an RSA signature for a hash you already computed and provide.
|
||||
* You should have created the hash before calling this by iterating over the
|
||||
* actual payload you need to confirm.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in,
|
||||
enum lws_genhash_types hash_type,
|
||||
uint8_t *sig, size_t sig_len);
|
||||
|
||||
/** lws_genrsa_public_decrypt_destroy() - Destroy RSA public decrypt context
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
*
|
||||
* Destroys any allocations related to \p ctx.
|
||||
*
|
||||
* This and related APIs operate identically with OpenSSL or mbedTLS backends.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_genrsa_destroy(struct lws_genrsa_ctx *ctx);
|
||||
|
||||
/** lws_genrsa_render_pkey_asn1() - Exports public or private key to ASN1/DER
|
||||
*
|
||||
* \param ctx: your struct lws_genrsa_ctx
|
||||
* \param _private: 0 = public part only, 1 = all parts of the key
|
||||
* \param pkey_asn1: pointer to buffer to take the ASN1
|
||||
* \param pkey_asn1_len: max size of the pkey_asn1_len
|
||||
*
|
||||
* Returns length of pkey_asn1 written, or -1 for error.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_genrsa_render_pkey_asn1(struct lws_genrsa_ctx *ctx, int _private,
|
||||
uint8_t *pkey_asn1, size_t pkey_asn1_len);
|
||||
///@}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Generic GPIO ops
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is like an abstract class for gpio, a real implementation provides
|
||||
* functions for the ops that use the underlying OS gpio arrangements.
|
||||
*/
|
||||
|
||||
#if !defined(__LWS_GPIO_H__)
|
||||
#define __LWS_GPIO_H__
|
||||
|
||||
typedef int _lws_plat_gpio_t;
|
||||
|
||||
typedef enum {
|
||||
LWSGGPIO_IRQ_NONE,
|
||||
LWSGGPIO_IRQ_RISING,
|
||||
LWSGGPIO_IRQ_FALLING,
|
||||
LWSGGPIO_IRQ_CHANGE,
|
||||
LWSGGPIO_IRQ_LOW,
|
||||
LWSGGPIO_IRQ_HIGH
|
||||
} lws_gpio_irq_t;
|
||||
|
||||
enum {
|
||||
LWSGGPIO_FL_READ = (1 << 0),
|
||||
LWSGGPIO_FL_WRITE = (1 << 1),
|
||||
LWSGGPIO_FL_PULLUP = (1 << 2),
|
||||
LWSGGPIO_FL_PULLDOWN = (1 << 3),
|
||||
LWSGGPIO_FL_START_LOW = (1 << 4),
|
||||
};
|
||||
|
||||
typedef void (*lws_gpio_irq_cb_t)(void *arg);
|
||||
|
||||
typedef struct lws_gpio_ops {
|
||||
void (*mode)(_lws_plat_gpio_t gpio, int flags);
|
||||
int (*read)(_lws_plat_gpio_t gpio);
|
||||
void (*set)(_lws_plat_gpio_t gpio, int val);
|
||||
int (*irq_mode)(_lws_plat_gpio_t gpio, lws_gpio_irq_t irq,
|
||||
lws_gpio_irq_cb_t cb, void *arg);
|
||||
} lws_gpio_ops_t;
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Generic I2C ops
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is like an abstract class for i2c, a real implementation provides
|
||||
* functions for the ops that use the underlying OS arrangements.
|
||||
*/
|
||||
|
||||
#if !defined(__LWS_I2C_H__)
|
||||
#define __LWS_I2C_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct lws_i2c_ops {
|
||||
int (*init)(const struct lws_i2c_ops *ctx);
|
||||
int (*start)(const struct lws_i2c_ops *ctx);
|
||||
void (*stop)(const struct lws_i2c_ops *ctx);
|
||||
int (*write)(const struct lws_i2c_ops *ctx, uint8_t data);
|
||||
int (*read)(const struct lws_i2c_ops *ctx);
|
||||
void (*set_ack)(const struct lws_i2c_ops *octx, int ack);
|
||||
} lws_i2c_ops_t;
|
||||
|
||||
/*
|
||||
* These are implemented by calling the ops above, and so are generic
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_i2c_command(const lws_i2c_ops_t *ctx, uint8_t ads7, uint8_t c);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_i2c_command_list(const lws_i2c_ops_t *ctx, uint8_t ads7, const uint8_t *buf,
|
||||
size_t len);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* lws abstract display implementation for ili9341 on spi
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(__LWS_DISPLAY_ILI9341_SPI_H__)
|
||||
#define __LWS_DISPLAY_ILI9341_SPI_H__
|
||||
|
||||
|
||||
typedef struct lws_display_ili9341 {
|
||||
|
||||
lws_display_t disp; /* use lws_display_ili9341_ops to set */
|
||||
const lws_spi_ops_t *spi; /* spi ops */
|
||||
|
||||
const lws_gpio_ops_t *gpio; /* NULL or gpio ops */
|
||||
_lws_plat_gpio_t reset_gpio; /* if gpio ops, nReset gpio # */
|
||||
|
||||
uint8_t spi_index; /* cs index starting from 0 */
|
||||
|
||||
} lws_display_ili9341_t;
|
||||
|
||||
int
|
||||
lws_display_ili9341_spi_init(const struct lws_display *disp);
|
||||
int
|
||||
lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src,
|
||||
lws_display_scalar x, lws_display_scalar y,
|
||||
lws_display_scalar w, lws_display_scalar h);
|
||||
int
|
||||
lws_display_ili9341_spi_power(const struct lws_display *disp, int state);
|
||||
|
||||
#define lws_display_ili9341_ops \
|
||||
.init = lws_display_ili9341_spi_init, \
|
||||
.blit = lws_display_ili9341_spi_blit, \
|
||||
.power = lws_display_ili9341_spi_power
|
||||
#endif
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
enum lws_jws_jose_hdr_indexes {
|
||||
LJJHI_ALG, /* REQUIRED */
|
||||
LJJHI_JKU, /* Optional: string */
|
||||
LJJHI_JWK, /* Optional: jwk JSON object: public key: */
|
||||
LJJHI_KID, /* Optional: string */
|
||||
LJJHI_X5U, /* Optional: string: url of public key cert / chain */
|
||||
LJJHI_X5C, /* Optional: base64 (NOT -url): actual cert */
|
||||
LJJHI_X5T, /* Optional: base64url: SHA-1 of actual cert */
|
||||
LJJHI_X5T_S256, /* Optional: base64url: SHA-256 of actual cert */
|
||||
LJJHI_TYP, /* Optional: string: media type */
|
||||
LJJHI_CTY, /* Optional: string: content media type */
|
||||
LJJHI_CRIT, /* Optional for send, REQUIRED: array of strings:
|
||||
* mustn't contain standardized strings or null set */
|
||||
|
||||
LJJHI_RECIPS_HDR,
|
||||
LJJHI_RECIPS_HDR_ALG,
|
||||
LJJHI_RECIPS_HDR_KID,
|
||||
LJJHI_RECIPS_EKEY,
|
||||
|
||||
LJJHI_ENC, /* JWE only: Optional: string */
|
||||
LJJHI_ZIP, /* JWE only: Optional: string ("DEF" = deflate) */
|
||||
|
||||
LJJHI_EPK, /* Additional arg for JWE ECDH: ephemeral public key */
|
||||
LJJHI_APU, /* Additional arg for JWE ECDH: base64url */
|
||||
LJJHI_APV, /* Additional arg for JWE ECDH: base64url */
|
||||
LJJHI_IV, /* Additional arg for JWE AES: base64url */
|
||||
LJJHI_TAG, /* Additional arg for JWE AES: base64url */
|
||||
LJJHI_P2S, /* Additional arg for JWE PBES2: base64url: salt */
|
||||
LJJHI_P2C, /* Additional arg for JWE PBES2: integer: count */
|
||||
|
||||
LWS_COUNT_JOSE_HDR_ELEMENTS
|
||||
};
|
||||
|
||||
enum lws_jose_algtype {
|
||||
LWS_JOSE_ENCTYPE_NONE,
|
||||
|
||||
LWS_JOSE_ENCTYPE_RSASSA_PKCS1_1_5,
|
||||
LWS_JOSE_ENCTYPE_RSASSA_PKCS1_OAEP,
|
||||
LWS_JOSE_ENCTYPE_RSASSA_PKCS1_PSS,
|
||||
|
||||
LWS_JOSE_ENCTYPE_ECDSA,
|
||||
LWS_JOSE_ENCTYPE_ECDHES,
|
||||
|
||||
LWS_JOSE_ENCTYPE_AES_CBC,
|
||||
LWS_JOSE_ENCTYPE_AES_CFB128,
|
||||
LWS_JOSE_ENCTYPE_AES_CFB8,
|
||||
LWS_JOSE_ENCTYPE_AES_CTR,
|
||||
LWS_JOSE_ENCTYPE_AES_ECB,
|
||||
LWS_JOSE_ENCTYPE_AES_OFB,
|
||||
LWS_JOSE_ENCTYPE_AES_XTS, /* care: requires double-length key */
|
||||
LWS_JOSE_ENCTYPE_AES_GCM,
|
||||
};
|
||||
|
||||
/* there's a table of these defined in lws-gencrypto-common.c */
|
||||
|
||||
struct lws_jose_jwe_alg {
|
||||
enum lws_genhash_types hash_type;
|
||||
enum lws_genhmac_types hmac_type;
|
||||
enum lws_jose_algtype algtype_signing; /* the signing cipher */
|
||||
enum lws_jose_algtype algtype_crypto; /* the encryption cipher */
|
||||
const char *alg; /* the JWA enc alg name, eg "ES512" */
|
||||
const char *curve_name; /* NULL, or, eg, "P-256" */
|
||||
unsigned short keybits_min, keybits_fixed;
|
||||
unsigned short ivbits;
|
||||
};
|
||||
|
||||
/*
|
||||
* For JWS, "JOSE header" is defined to be the union of...
|
||||
*
|
||||
* o JWS Protected Header
|
||||
* o JWS Unprotected Header
|
||||
*
|
||||
* For JWE, the "JOSE header" is the union of...
|
||||
*
|
||||
* o JWE Protected Header
|
||||
* o JWE Shared Unprotected Header
|
||||
* o JWE Per-Recipient Unprotected Header
|
||||
*/
|
||||
|
||||
#define LWS_JWS_MAX_RECIPIENTS 3
|
||||
|
||||
struct lws_jws_recpient {
|
||||
/*
|
||||
* JOSE per-recipient unprotected header... for JWS this contains
|
||||
* protected / header / signature
|
||||
*/
|
||||
struct lws_gencrypto_keyelem unprot[LWS_COUNT_JOSE_HDR_ELEMENTS];
|
||||
struct lws_jwk jwk_ephemeral; /* recipient ephemeral key if any */
|
||||
struct lws_jwk jwk; /* recipient "jwk" key if any */
|
||||
};
|
||||
|
||||
struct lws_jose {
|
||||
/* JOSE protected and unprotected header elements */
|
||||
struct lws_gencrypto_keyelem e[LWS_COUNT_JOSE_HDR_ELEMENTS];
|
||||
|
||||
struct lws_jws_recpient recipient[LWS_JWS_MAX_RECIPIENTS];
|
||||
|
||||
char typ[32];
|
||||
|
||||
/* information from the protected header part */
|
||||
const struct lws_jose_jwe_alg *alg;
|
||||
const struct lws_jose_jwe_alg *enc_alg;
|
||||
|
||||
int recipients; /* count of used recipient[] entries */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_jose_init() - prepare a struct lws_jose for use
|
||||
*
|
||||
* \param jose: the jose header struct to prepare
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jose_init(struct lws_jose *jose);
|
||||
|
||||
/**
|
||||
* lws_jose_destroy() - retire a struct lws_jose from use
|
||||
*
|
||||
* \param jose: the jose header struct to destroy
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jose_destroy(struct lws_jose *jose);
|
||||
|
||||
/**
|
||||
* lws_gencrypto_jws_alg_to_definition() - look up a jws alg name
|
||||
*
|
||||
* \param alg: the jws alg name
|
||||
* \param jose: pointer to the pointer to the info struct to set on success
|
||||
*
|
||||
* Returns 0 if *jose set, else nonzero for failure
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_gencrypto_jws_alg_to_definition(const char *alg,
|
||||
const struct lws_jose_jwe_alg **jose);
|
||||
|
||||
/**
|
||||
* lws_gencrypto_jwe_alg_to_definition() - look up a jwe alg name
|
||||
*
|
||||
* \param alg: the jwe alg name
|
||||
* \param jose: pointer to the pointer to the info struct to set on success
|
||||
*
|
||||
* Returns 0 if *jose set, else nonzero for failure
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_gencrypto_jwe_alg_to_definition(const char *alg,
|
||||
const struct lws_jose_jwe_alg **jose);
|
||||
|
||||
/**
|
||||
* lws_gencrypto_jwe_enc_to_definition() - look up a jwe enc name
|
||||
*
|
||||
* \param alg: the jwe enc name
|
||||
* \param jose: pointer to the pointer to the info struct to set on success
|
||||
*
|
||||
* Returns 0 if *jose set, else nonzero for failure
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_gencrypto_jwe_enc_to_definition(const char *enc,
|
||||
const struct lws_jose_jwe_alg **jose);
|
||||
|
||||
/**
|
||||
* lws_jws_parse_jose() - parse a JWS JOSE header
|
||||
*
|
||||
* \param jose: the jose struct to set to parsing results
|
||||
* \param buf: the raw JOSE header
|
||||
* \param len: the length of the raw JOSE header
|
||||
* \param temp: parent-owned buffer to "allocate" elements into
|
||||
* \param temp_len: amount of space available in temp
|
||||
*
|
||||
* returns the amount of temp used, or -1 for error
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_parse_jose(struct lws_jose *jose,
|
||||
const char *buf, int len, char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jwe_parse_jose() - parse a JWE JOSE header
|
||||
*
|
||||
* \param jose: the jose struct to set to parsing results
|
||||
* \param buf: the raw JOSE header
|
||||
* \param len: the length of the raw JOSE header
|
||||
* \param temp: parent-owned buffer to "allocate" elements into
|
||||
* \param temp_len: amount of space available in temp
|
||||
*
|
||||
* returns the amount of temp used, or -1 for error
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_parse_jose(struct lws_jose *jose,
|
||||
const char *buf, int len, char *temp, int *temp_len);
|
||||
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* JWE Compact Serialization consists of
|
||||
*
|
||||
* BASE64URL(UTF8(JWE Protected Header)) || '.' ||
|
||||
* BASE64URL(JWE Encrypted Key) || '.' ||
|
||||
* BASE64URL(JWE Initialization Vector) || '.' ||
|
||||
* BASE64URL(JWE Ciphertext) || '.' ||
|
||||
* BASE64URL(JWE Authentication Tag)
|
||||
*/
|
||||
|
||||
#define LWS_JWE_RFC3394_OVERHEAD_BYTES 8
|
||||
#define LWS_JWE_AES_IV_BYTES 16
|
||||
|
||||
#define LWS_JWE_LIMIT_RSA_KEY_BITS 4096
|
||||
#define LWS_JWE_LIMIT_AES_KEY_BITS (512 + 64) /* RFC3394 Key Wrap adds 64b */
|
||||
#define LWS_JWE_LIMIT_EC_KEY_BITS 528 /* 521 rounded to byte boundary */
|
||||
#define LWS_JWE_LIMIT_HASH_BITS (LWS_GENHASH_LARGEST * 8)
|
||||
|
||||
/* the largest key element for any cipher */
|
||||
#define LWS_JWE_LIMIT_KEY_ELEMENT_BYTES (LWS_JWE_LIMIT_RSA_KEY_BITS / 8)
|
||||
|
||||
|
||||
struct lws_jwe {
|
||||
struct lws_jose jose;
|
||||
struct lws_jws jws;
|
||||
struct lws_jwk jwk;
|
||||
|
||||
/*
|
||||
* We have to keep a copy of the CEK so we can reuse it with later
|
||||
* key encryptions for the multiple recipient case.
|
||||
*/
|
||||
uint8_t cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
|
||||
unsigned int cek_valid:1;
|
||||
|
||||
int recip;
|
||||
};
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jwe_init(struct lws_jwe *jwe, struct lws_context *context);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jwe_destroy(struct lws_jwe *jwe);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jwe_be64(uint64_t c, uint8_t *p8);
|
||||
|
||||
/*
|
||||
* JWE Compact Serialization consists of
|
||||
*
|
||||
* BASE64URL(UTF8(JWE Protected Header)) || '.' ||
|
||||
* BASE64URL(JWE Encrypted Key) || '.' ||
|
||||
* BASE64URL(JWE Initialization Vector) || '.' ||
|
||||
* BASE64URL(JWE Ciphertext) || '.' ||
|
||||
* BASE64URL(JWE Authentication Tag)
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_render_compact(struct lws_jwe *jwe, char *out, size_t out_len);
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_jwe_render_flattened(struct lws_jwe *jwe, char *out, size_t out_len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_json_parse(struct lws_jwe *jwe, const uint8_t *buf, int len,
|
||||
char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jwe_auth_and_decrypt() - confirm and decrypt JWE
|
||||
*
|
||||
* \param jose: jose context
|
||||
* \param jws: jws / jwe context... .map and .map_b64 must be filled already
|
||||
*
|
||||
* This is a high level JWE decrypt api that takes a jws with the maps
|
||||
* already processed, and if the authentication passes, returns the decrypted
|
||||
* plaintext in jws.map.buf[LJWE_CTXT] and its length in jws.map.len[LJWE_CTXT].
|
||||
*
|
||||
* In the jws, the following fields must have been set by the caller
|
||||
*
|
||||
* .context
|
||||
* .jwk (the key encryption key)
|
||||
* .map
|
||||
* .map_b64
|
||||
*
|
||||
* Having the b64 and decoded maps filled externally makes it flexible where
|
||||
* the data was picked from, eg, from a Complete JWE JSON serialization, a
|
||||
* flattened one, or a Compact Serialization.
|
||||
*
|
||||
* Returns decrypt length, or -1 for failure.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_auth_and_decrypt(struct lws_jwe *jwe, char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jwe_encrypt() - perform JWE encryption
|
||||
*
|
||||
* \param jose: the JOSE header information (encryption types, etc)
|
||||
* \param jws: the JWE elements, pointer to jwk etc
|
||||
* \param temp: parent-owned buffer to "allocate" elements into
|
||||
* \param temp_len: amount of space available in temp
|
||||
*
|
||||
* May be called up to LWS_JWS_MAX_RECIPIENTS times to encrypt the same CEK
|
||||
* multiple ways on the same JWE payload.
|
||||
*
|
||||
* returns the amount of temp used, or -1 for error.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_encrypt(struct lws_jwe *jwe, char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jwe_create_packet() - add b64 sig to b64 hdr + payload
|
||||
*
|
||||
* \param jwe: the struct lws_jwe we are trying to render
|
||||
* \param payload: unencoded payload JSON
|
||||
* \param len: length of unencoded payload JSON
|
||||
* \param nonce: Nonse string to include in protected header
|
||||
* \param out: buffer to take signed packet
|
||||
* \param out_len: size of \p out buffer
|
||||
* \param conext: lws_context to get random from
|
||||
*
|
||||
* This creates a "flattened" JWS packet from the jwk and the plaintext
|
||||
* payload, and signs it. The packet is written into \p out.
|
||||
*
|
||||
* This does the whole packet assembly and signing, calling through to
|
||||
* lws_jws_sign_from_b64() as part of the process.
|
||||
*
|
||||
* Returns the length written to \p out, or -1.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_create_packet(struct lws_jwe *jwe,
|
||||
const char *payload, size_t len, const char *nonce,
|
||||
char *out, size_t out_len, struct lws_context *context);
|
||||
|
||||
|
||||
/* only exposed because we have test vectors that need it */
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwe_auth_and_decrypt_cbc_hs(struct lws_jwe *jwe, uint8_t *enc_cek,
|
||||
uint8_t *aad, int aad_len);
|
||||
|
||||
/* only exposed because we have test vectors that need it */
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwa_concat_kdf(struct lws_jwe *jwe, int direct,
|
||||
uint8_t *out, const uint8_t *shared_secret, int sslen);
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup jwk JSON Web Keys
|
||||
* ## JSON Web Keys API
|
||||
*
|
||||
* Lws provides an API to parse JSON Web Keys into a struct lws_gencrypto_keyelem.
|
||||
*
|
||||
* "oct" and "RSA" type keys are supported. For "oct" keys, they are held in
|
||||
* the "e" member of the struct lws_gencrypto_keyelem.
|
||||
*
|
||||
* Keys elements are allocated on the heap. You must destroy the allocations
|
||||
* in the struct lws_gencrypto_keyelem by calling
|
||||
* lws_genrsa_destroy_elements() when you are finished with it.
|
||||
*/
|
||||
///@{
|
||||
|
||||
enum enum_jwk_meta_tok {
|
||||
JWK_META_KTY,
|
||||
JWK_META_KID,
|
||||
JWK_META_USE,
|
||||
JWK_META_KEY_OPS,
|
||||
JWK_META_X5C,
|
||||
JWK_META_ALG,
|
||||
|
||||
LWS_COUNT_JWK_ELEMENTS
|
||||
};
|
||||
|
||||
struct lws_jwk {
|
||||
/* key data elements */
|
||||
struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_MAX_KEYEL_COUNT];
|
||||
/* generic meta key elements, like KID */
|
||||
struct lws_gencrypto_keyelem meta[LWS_COUNT_JWK_ELEMENTS];
|
||||
int kty; /**< one of LWS_GENCRYPTO_KTY_ */
|
||||
char private_key; /* nonzero = has private key elements */
|
||||
};
|
||||
|
||||
typedef int (*lws_jwk_key_import_callback)(struct lws_jwk *s, void *user);
|
||||
|
||||
struct lws_jwk_parse_state {
|
||||
struct lws_jwk *jwk;
|
||||
char b64[(((8192 / 8) * 4) / 3) + 1]; /* enough for 8Kb key */
|
||||
lws_jwk_key_import_callback per_key_cb;
|
||||
void *user;
|
||||
int pos;
|
||||
int cose_state;
|
||||
int seen;
|
||||
unsigned short possible;
|
||||
};
|
||||
|
||||
/** lws_jwk_import() - Create a JSON Web key from the textual representation
|
||||
*
|
||||
* \param jwk: the JWK object to create
|
||||
* \param cb: callback for each jwk-processed key, or NULL if importing a single
|
||||
* key with no parent "keys" JSON
|
||||
* \param user: pointer to be passed to the callback, otherwise ignored by lws.
|
||||
* NULL if importing a single key with no parent "keys" JSON
|
||||
* \param in: a single JWK JSON stanza in utf-8
|
||||
* \param len: the length of the JWK JSON stanza in bytes
|
||||
*
|
||||
* Creates an lws_jwk struct filled with data from the JSON representation.
|
||||
*
|
||||
* There are two ways to use this... with some protocols a single jwk is
|
||||
* delivered with no parent "keys": [] array. If you call this with cb and
|
||||
* user as NULL, then the input will be interpreted like that and the results
|
||||
* placed in s.
|
||||
*
|
||||
* The second case is that you are dealing with a "keys":[] array with one or
|
||||
* more keys in it. In this case, the function iterates through the keys using
|
||||
* s as a temporary jwk, and calls the user-provided callback for each key in
|
||||
* turn while it return 0 (nonzero return from the callback terminates the
|
||||
* iteration through any further keys).
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_import(struct lws_jwk *jwk, lws_jwk_key_import_callback cb, void *user,
|
||||
const char *in, size_t len);
|
||||
|
||||
/** lws_jwk_destroy() - Destroy a JSON Web key
|
||||
*
|
||||
* \param jwk: the JWK object to destroy
|
||||
*
|
||||
* All allocations in the lws_jwk are destroyed
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jwk_destroy(struct lws_jwk *jwk);
|
||||
|
||||
/** lws_jwk_dup_oct() - Set a jwk to a dup'd binary OCT key
|
||||
*
|
||||
* \param jwk: the JWK object to set
|
||||
* \param key: the JWK object to destroy
|
||||
* \param len: the JWK object to destroy
|
||||
*
|
||||
* Sets the kty to OCT, allocates len bytes for K and copies len bytes of key
|
||||
* into the allocation.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_dup_oct(struct lws_jwk *jwk, const void *key, int len);
|
||||
|
||||
#define LWSJWKF_EXPORT_PRIVATE (1 << 0)
|
||||
#define LWSJWKF_EXPORT_NOCRLF (1 << 1)
|
||||
|
||||
/** lws_jwk_export() - Export a JSON Web key to a textual representation
|
||||
*
|
||||
* \param jwk: the JWK object to export
|
||||
* \param flags: control export options
|
||||
* \param p: the buffer to write the exported JWK to
|
||||
* \param len: the length of the buffer \p p in bytes... reduced by used amount
|
||||
*
|
||||
* Returns length of the used part of the buffer if OK, or -1 for error.
|
||||
*
|
||||
* \p flags can be OR-ed together
|
||||
*
|
||||
* LWSJWKF_EXPORT_PRIVATE: default is only public part, set this to also export
|
||||
* the private part
|
||||
*
|
||||
* LWSJWKF_EXPORT_NOCRLF: normally adds a CRLF at the end of the export, if
|
||||
* you need to suppress it, set this flag
|
||||
*
|
||||
* Serializes the content of the JWK into a char buffer.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_export(struct lws_jwk *jwk, int flags, char *p, int *len);
|
||||
|
||||
/** lws_jwk_load() - Import a JSON Web key from a file
|
||||
*
|
||||
* \param jwk: the JWK object to load into
|
||||
* \param filename: filename to load from
|
||||
* \param cb: optional callback for each key
|
||||
* \param user: opaque user pointer passed to cb if given
|
||||
*
|
||||
* Returns 0 for OK or -1 for failure
|
||||
*
|
||||
* There are two ways to use this... with some protocols a single jwk is
|
||||
* delivered with no parent "keys": [] array. If you call this with cb and
|
||||
* user as NULL, then the input will be interpreted like that and the results
|
||||
* placed in s.
|
||||
*
|
||||
* The second case is that you are dealing with a "keys":[] array with one or
|
||||
* more keys in it. In this case, the function iterates through the keys using
|
||||
* s as a temporary jwk, and calls the user-provided callback for each key in
|
||||
* turn while it return 0 (nonzero return from the callback terminates the
|
||||
* iteration through any further keys, leaving the last one in s).
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_load(struct lws_jwk *jwk, const char *filename,
|
||||
lws_jwk_key_import_callback cb, void *user);
|
||||
|
||||
/** lws_jwk_save() - Export a JSON Web key to a file
|
||||
*
|
||||
* \param jwk: the JWK object to save from
|
||||
* \param filename: filename to save to
|
||||
*
|
||||
* Returns 0 for OK or -1 for failure
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_save(struct lws_jwk *jwk, const char *filename);
|
||||
|
||||
/** lws_jwk_rfc7638_fingerprint() - jwk to RFC7638 compliant fingerprint
|
||||
*
|
||||
* \param jwk: the JWK object to fingerprint
|
||||
* \param digest32: buffer to take 32-byte digest
|
||||
*
|
||||
* Returns 0 for OK or -1 for failure
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_rfc7638_fingerprint(struct lws_jwk *jwk, char *digest32);
|
||||
|
||||
/** lws_jwk_strdup_meta() - allocate a duplicated string meta element
|
||||
*
|
||||
* \param jwk: the JWK object to fingerprint
|
||||
* \param idx: JWK_META_ element index
|
||||
* \param in: string to copy
|
||||
* \param len: length of string to copy
|
||||
*
|
||||
* Returns 0 for OK or -1 for failure
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_strdup_meta(struct lws_jwk *jwk, enum enum_jwk_meta_tok idx,
|
||||
const char *in, int len);
|
||||
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwk_dump(struct lws_jwk *jwk);
|
||||
|
||||
/** lws_jwk_generate() - create a new key of given type and characteristics
|
||||
*
|
||||
* \param context: the struct lws_context used for RNG
|
||||
* \param jwk: the JWK object to fingerprint
|
||||
* \param kty: One of the LWS_GENCRYPTO_KTY_ key types
|
||||
* \param bits: for OCT and RSA keys, the number of bits
|
||||
* \param curve: for EC keys, the name of the curve
|
||||
*
|
||||
* Returns 0 for OK or -1 for failure
|
||||
*/
|
||||
LWS_VISIBLE int
|
||||
lws_jwk_generate(struct lws_context *context, struct lws_jwk *jwk,
|
||||
enum lws_gencrypto_kty kty, int bits, const char *curve);
|
||||
|
||||
///@}
|
||||
|
|
@ -1,599 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*! \defgroup jws JSON Web Signature
|
||||
* ## JSON Web Signature API
|
||||
*
|
||||
* Lws provides an API to check and create RFC7515 JSON Web Signatures
|
||||
*
|
||||
* SHA256/384/512 HMAC, and RSA 256/384/512 are supported.
|
||||
*
|
||||
* The API uses your TLS library crypto, but works exactly the same no matter
|
||||
* what your TLS backend is.
|
||||
*/
|
||||
///@{
|
||||
|
||||
/*
|
||||
* The maps are built to work with both JWS (LJWS_) and JWE (LJWE_), and are
|
||||
* sized to the slightly larger JWE case.
|
||||
*/
|
||||
|
||||
enum enum_jws_sig_elements {
|
||||
|
||||
/* JWS block namespace */
|
||||
LJWS_JOSE,
|
||||
LJWS_PYLD,
|
||||
LJWS_SIG,
|
||||
LJWS_UHDR,
|
||||
|
||||
/* JWE block namespace */
|
||||
LJWE_JOSE = 0,
|
||||
LJWE_EKEY,
|
||||
LJWE_IV,
|
||||
LJWE_CTXT,
|
||||
LJWE_ATAG,
|
||||
LJWE_AAD,
|
||||
|
||||
LWS_JWS_MAX_COMPACT_BLOCKS
|
||||
};
|
||||
|
||||
struct lws_jws_map {
|
||||
const char *buf[LWS_JWS_MAX_COMPACT_BLOCKS];
|
||||
uint32_t len[LWS_JWS_MAX_COMPACT_BLOCKS];
|
||||
};
|
||||
|
||||
#define LWS_JWS_MAX_SIGS 3
|
||||
|
||||
struct lws_jws {
|
||||
struct lws_jwk *jwk; /* the struct lws_jwk containing the signing key */
|
||||
struct lws_context *context; /* the lws context (used to get random) */
|
||||
struct lws_jws_map map, map_b64;
|
||||
};
|
||||
|
||||
/* jws EC signatures do not have ASN.1 in them, meaning they're incompatible
|
||||
* with generic signatures.
|
||||
*/
|
||||
|
||||
/**
|
||||
* lws_jws_init() - initialize a jws for use
|
||||
*
|
||||
* \param jws: pointer to the jws to initialize
|
||||
* \param jwk: the jwk to use with this jws
|
||||
* \param context: the lws_context to use
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jws_init(struct lws_jws *jws, struct lws_jwk *jwk,
|
||||
struct lws_context *context);
|
||||
|
||||
/**
|
||||
* lws_jws_destroy() - scrub a jws
|
||||
*
|
||||
* \param jws: pointer to the jws to destroy
|
||||
*
|
||||
* Call before the jws goes out of scope.
|
||||
*
|
||||
* Elements defined in the jws are zeroed.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_jws_destroy(struct lws_jws *jws);
|
||||
|
||||
/**
|
||||
* lws_jws_sig_confirm_compact() - check signature
|
||||
*
|
||||
* \param map: pointers and lengths for each of the unencoded JWS elements
|
||||
* \param jwk: public key
|
||||
* \param context: lws_context
|
||||
* \param temp: scratchpad
|
||||
* \param temp_len: length of scratchpad
|
||||
*
|
||||
* Confirms the signature on a JWS. Use if you have non-b64 plain JWS elements
|
||||
* in a map... it'll make a temp b64 version needed for comparison. See below
|
||||
* for other variants.
|
||||
*
|
||||
* Returns 0 on match.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_sig_confirm_compact(struct lws_jws_map *map, struct lws_jwk *jwk,
|
||||
struct lws_context *context,
|
||||
char *temp, int *temp_len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_sig_confirm_compact_b64_map(struct lws_jws_map *map_b64,
|
||||
struct lws_jwk *jwk,
|
||||
struct lws_context *context,
|
||||
char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jws_sig_confirm_compact_b64() - check signature on b64 compact JWS
|
||||
*
|
||||
* \param in: pointer to b64 jose.payload[.hdr].sig
|
||||
* \param len: bytes available at \p in
|
||||
* \param map: map to take decoded non-b64 content
|
||||
* \param jwk: public key
|
||||
* \param context: lws_context
|
||||
* \param temp: scratchpad
|
||||
* \param temp_len: size of scratchpad
|
||||
*
|
||||
* Confirms the signature on a JWS. Use if you have you have b64 compact layout
|
||||
* (jose.payload.hdr.sig) as an aggregated string... it'll make a temp plain
|
||||
* version needed for comparison.
|
||||
*
|
||||
* Returns 0 on match.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_sig_confirm_compact_b64(const char *in, size_t len,
|
||||
struct lws_jws_map *map,
|
||||
struct lws_jwk *jwk,
|
||||
struct lws_context *context,
|
||||
char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jws_sig_confirm() - check signature on plain + b64 JWS elements
|
||||
*
|
||||
* \param map_b64: pointers and lengths for each of the b64-encoded JWS elements
|
||||
* \param map: pointers and lengths for each of the unencoded JWS elements
|
||||
* \param jwk: public key
|
||||
* \param context: lws_context
|
||||
*
|
||||
* Confirms the signature on a JWS. Use if you have you already have both b64
|
||||
* compact layout (jose.payload.hdr.sig) and decoded JWS elements in maps.
|
||||
*
|
||||
* If you had the b64 string and called lws_jws_compact_decode() on it, you
|
||||
* will end up with both maps, and can use this api version, saving needlessly
|
||||
* regenerating any temp map.
|
||||
*
|
||||
* Returns 0 on match.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_sig_confirm(struct lws_jws_map *map_b64, /* b64-encoded */
|
||||
struct lws_jws_map *map, /* non-b64 */
|
||||
struct lws_jwk *jwk, struct lws_context *context);
|
||||
|
||||
/**
|
||||
* lws_jws_sign_from_b64() - add b64 sig to b64 hdr + payload
|
||||
*
|
||||
* \param jose: jose header information
|
||||
* \param jws: information to include in the signature
|
||||
* \param b64_sig: output buffer for b64 signature
|
||||
* \param sig_len: size of \p b64_sig output buffer
|
||||
*
|
||||
* This adds a b64-coded JWS signature of the b64-encoded protected header
|
||||
* and b64-encoded payload, at \p b64_sig. The signature will be as large
|
||||
* as the N element of the RSA key when the RSA key is used, eg, 512 bytes for
|
||||
* a 4096-bit key, and then b64-encoding on top.
|
||||
*
|
||||
* In some special cases, there is only payload to sign and no header, in that
|
||||
* case \p b64_hdr may be NULL, and only the payload will be hashed before
|
||||
* signing.
|
||||
*
|
||||
* Returns the length of the encoded signature written to \p b64_sig, or -1.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_sign_from_b64(struct lws_jose *jose, struct lws_jws *jws, char *b64_sig,
|
||||
size_t sig_len);
|
||||
|
||||
/**
|
||||
* lws_jws_compact_decode() - converts and maps compact serialization b64 sections
|
||||
*
|
||||
* \param in: the incoming compact serialized b64
|
||||
* \param len: the length of the incoming compact serialized b64
|
||||
* \param map: pointer to the results structure
|
||||
* \param map_b64: NULL, or pointer to a second results structure taking block
|
||||
* information about the undecoded b64
|
||||
* \param out: buffer to hold decoded results
|
||||
* \param out_len: size of out in bytes
|
||||
*
|
||||
* Returns number of sections (2 if "none", else 3), or -1 if illegal.
|
||||
*
|
||||
* map is set to point to the start and hold the length of each decoded block.
|
||||
* If map_b64 is non-NULL, then it's set with information about the input b64
|
||||
* blocks.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_compact_decode(const char *in, int len, struct lws_jws_map *map,
|
||||
struct lws_jws_map *map_b64, char *out, int *out_len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_compact_encode(struct lws_jws_map *map_b64, /* b64-encoded */
|
||||
const struct lws_jws_map *map, /* non-b64 */
|
||||
char *buf, int *out_len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_sig_confirm_json(const char *in, size_t len,
|
||||
struct lws_jws *jws, struct lws_jwk *jwk,
|
||||
struct lws_context *context,
|
||||
char *temp, int *temp_len);
|
||||
|
||||
/**
|
||||
* lws_jws_write_flattened_json() - create flattened JSON sig
|
||||
*
|
||||
* \param jws: information to include in the signature
|
||||
* \param flattened: output buffer for JSON
|
||||
* \param len: size of \p flattened output buffer
|
||||
*
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_write_flattened_json(struct lws_jws *jws, char *flattened, size_t len);
|
||||
|
||||
/**
|
||||
* lws_jws_write_compact() - create flattened JSON sig
|
||||
*
|
||||
* \param jws: information to include in the signature
|
||||
* \param compact: output buffer for compact format
|
||||
* \param len: size of \p flattened output buffer
|
||||
*
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_write_compact(struct lws_jws *jws, char *compact, size_t len);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* below apis are not normally needed if dealing with whole JWS... they're
|
||||
* useful for creating from scratch
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* lws_jws_dup_element() - allocate space for an element and copy data into it
|
||||
*
|
||||
* \param map: map to create the element in
|
||||
* \param idx: index of element in the map to create
|
||||
* \param temp: space to allocate in
|
||||
* \param temp_len: available space at temp
|
||||
* \param in: data to duplicate into element
|
||||
* \param in_len: length of data to duplicate
|
||||
* \param actual_alloc: 0 for same as in_len, else actual allocation size
|
||||
*
|
||||
* Copies in_len from in to temp, if temp_len is sufficient.
|
||||
*
|
||||
* Returns 0 or -1 if not enough space in temp / temp_len.
|
||||
*
|
||||
* Over-allocation can be acheived by setting actual_alloc to the real
|
||||
* allocation desired... in_len will be copied into it.
|
||||
*
|
||||
* *temp_len is reduced by actual_alloc if successful.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_dup_element(struct lws_jws_map *map, int idx,
|
||||
char *temp, int *temp_len, const void *in, size_t in_len,
|
||||
size_t actual_alloc);
|
||||
|
||||
/**
|
||||
* lws_jws_randomize_element() - create an element and fill with random
|
||||
*
|
||||
* \param context: lws_context used for random
|
||||
* \param map: map to create the element in
|
||||
* \param idx: index of element in the map to create
|
||||
* \param temp: space to allocate in
|
||||
* \param temp_len: available space at temp
|
||||
* \param random_len: length of data to fill with random
|
||||
* \param actual_alloc: 0 for same as random_len, else actual allocation size
|
||||
*
|
||||
* Randomize random_len bytes at temp, if temp_len is sufficient.
|
||||
*
|
||||
* Returns 0 or -1 if not enough space in temp / temp_len.
|
||||
*
|
||||
* Over-allocation can be acheived by setting actual_alloc to the real
|
||||
* allocation desired... the first random_len will be filled with random.
|
||||
*
|
||||
* *temp_len is reduced by actual_alloc if successful.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_randomize_element(struct lws_context *context,
|
||||
struct lws_jws_map *map,
|
||||
int idx, char *temp, int *temp_len, size_t random_len,
|
||||
size_t actual_alloc);
|
||||
|
||||
/**
|
||||
* lws_jws_alloc_element() - create an element and reserve space for content
|
||||
*
|
||||
* \param map: map to create the element in
|
||||
* \param idx: index of element in the map to create
|
||||
* \param temp: space to allocate in
|
||||
* \param temp_len: available space at temp
|
||||
* \param len: logical length of element
|
||||
* \param actual_alloc: 0 for same as len, else actual allocation size
|
||||
*
|
||||
* Allocate len bytes at temp, if temp_len is sufficient.
|
||||
*
|
||||
* Returns 0 or -1 if not enough space in temp / temp_len.
|
||||
*
|
||||
* Over-allocation can be acheived by setting actual_alloc to the real
|
||||
* allocation desired... the element logical length will be set to len.
|
||||
*
|
||||
* *temp_len is reduced by actual_alloc if successful.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_alloc_element(struct lws_jws_map *map, int idx, char *temp,
|
||||
int *temp_len, size_t len, size_t actual_alloc);
|
||||
|
||||
/**
|
||||
* lws_jws_encode_b64_element() - create an b64-encoded element
|
||||
*
|
||||
* \param map: map to create the element in
|
||||
* \param idx: index of element in the map to create
|
||||
* \param temp: space to allocate in
|
||||
* \param temp_len: available space at temp
|
||||
* \param in: pointer to unencoded input
|
||||
* \param in_len: length of unencoded input
|
||||
*
|
||||
* Allocate len bytes at temp, if temp_len is sufficient.
|
||||
*
|
||||
* Returns 0 or -1 if not enough space in temp / temp_len.
|
||||
*
|
||||
* Over-allocation can be acheived by setting actual_alloc to the real
|
||||
* allocation desired... the element logical length will be set to len.
|
||||
*
|
||||
* *temp_len is reduced by actual_alloc if successful.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_encode_b64_element(struct lws_jws_map *map, int idx,
|
||||
char *temp, int *temp_len, const void *in,
|
||||
size_t in_len);
|
||||
|
||||
|
||||
/**
|
||||
* lws_jws_b64_compact_map() - find block starts and lengths in compact b64
|
||||
*
|
||||
* \param in: pointer to b64 jose.payload[.hdr].sig
|
||||
* \param len: bytes available at \p in
|
||||
* \param map: output struct with pointers and lengths for each JWS element
|
||||
*
|
||||
* Scans a jose.payload[.hdr].sig b64 string and notes where the blocks start
|
||||
* and their length into \p map.
|
||||
*
|
||||
* Returns number of blocks if OK. May return <0 if malformed.
|
||||
* May not fill all map entries.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_b64_compact_map(const char *in, int len, struct lws_jws_map *map);
|
||||
|
||||
|
||||
/**
|
||||
* lws_jws_base64_enc() - encode input data into b64url data
|
||||
*
|
||||
* \param in: the incoming plaintext
|
||||
* \param in_len: the length of the incoming plaintext in bytes
|
||||
* \param out: the buffer to store the b64url encoded data to
|
||||
* \param out_max: the length of \p out in bytes
|
||||
*
|
||||
* Returns either -1 if problems, or the number of bytes written to \p out.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max);
|
||||
|
||||
/**
|
||||
* lws_jws_encode_section() - encode input data into b64url data,
|
||||
* prepending . if not first
|
||||
*
|
||||
* \param in: the incoming plaintext
|
||||
* \param in_len: the length of the incoming plaintext in bytes
|
||||
* \param first: nonzero if the first section
|
||||
* \param p: the buffer to store the b64url encoded data to
|
||||
* \param end: just past the end of p
|
||||
*
|
||||
* Returns either -1 if problems, or the number of bytes written to \p out.
|
||||
* If the section is not the first one, '.' is prepended.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jws_encode_section(const char *in, size_t in_len, int first, char **p,
|
||||
char *end);
|
||||
|
||||
/**
|
||||
* lws_jwt_signed_validate() - check a compact JWT against a key and alg
|
||||
*
|
||||
* \param ctx: the lws_context
|
||||
* \param jwk: the key for checking the signature
|
||||
* \param alg_list: the expected alg name, like "ES512"
|
||||
* \param com: the compact JWT
|
||||
* \param len: the length of com
|
||||
* \param temp: a temp scratchpad
|
||||
* \param tl: available length of temp scratchpad
|
||||
* \param out: the output buffer to hold the validated plaintext
|
||||
* \param out_len: on entry, max length of out; on exit, used length of out
|
||||
*
|
||||
* Returns nonzero if the JWT cannot be validated or the plaintext can't fit the
|
||||
* provided output buffer, or 0 if it is validated as being signed by the
|
||||
* provided jwk.
|
||||
*
|
||||
* If validated, the plaintext in the JWT is copied into out and out_len set to
|
||||
* the used length.
|
||||
*
|
||||
* temp can be discarded or reused after the call returned, it's used to hold
|
||||
* transformations of the B64 JWS in the JWT.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwt_signed_validate(struct lws_context *ctx, struct lws_jwk *jwk,
|
||||
const char *alg_list, const char *com, size_t len,
|
||||
char *temp, int tl, char *out, size_t *out_len);
|
||||
|
||||
/**
|
||||
* lws_jwt_sign_compact() - generate a compact JWT using a key and alg
|
||||
*
|
||||
* \param ctx: the lws_context
|
||||
* \param jwk: the signing key
|
||||
* \param alg: the signing alg name, like "ES512"
|
||||
* \param out: the output buffer to hold the signed JWT in compact form
|
||||
* \param out_len: on entry, the length of out; on exit, the used amount of out
|
||||
* \param temp: a temp scratchpad
|
||||
* \param tl: available length of temp scratchpad
|
||||
* \param format: a printf style format specification
|
||||
* \param ...: zero or more args for the format specification
|
||||
*
|
||||
* Creates a JWT in a single step, from the format string and args through to
|
||||
* outputting a well-formed compact JWT representation in out.
|
||||
*
|
||||
* Returns 0 if all is well and *out_len is the amount of data in out, else
|
||||
* nonzero if failed. Temp must be large enough to hold various intermediate
|
||||
* representations.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwt_sign_compact(struct lws_context *ctx, struct lws_jwk *jwk,
|
||||
const char *alg, char *out, size_t *out_len, char *temp,
|
||||
int tl, const char *format, ...) LWS_FORMAT(8);
|
||||
|
||||
struct lws_jwt_sign_info {
|
||||
const char *alg;
|
||||
/**< entry: signing alg name, like "RS256" */
|
||||
const char *jose_hdr;
|
||||
/**< entry: optional JOSE hdr; if present, alg field is ignored; instead the
|
||||
* whole claim object has to be provided in this parameter */
|
||||
size_t jose_hdr_len;
|
||||
/**< entry: if jose_hdr is not NULL, JOSE header length without terminating '\0' */
|
||||
char *out;
|
||||
/**< exit: signed JWT in compact form*/
|
||||
size_t *out_len;
|
||||
/**< entry,exit: buffer size of out; actual size of JWT on exit */
|
||||
char *temp;
|
||||
/**< exit undefined content, used by the function as a temporary scratchpad; MUST
|
||||
* be large enogh to store various intermediate representations */
|
||||
int tl;
|
||||
/**< entry: size of temp buffer */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_jwt_sign_compact() - generate a compact JWT using a key and JOSE header
|
||||
*
|
||||
* \param ctx: the lws_context
|
||||
* \param jwk: the signing key
|
||||
* \param info: info describing the JWT's content and output/temp buffers
|
||||
* \param format: a printf style format specification of the claims object
|
||||
* \param ...: zero or more args for the format specification
|
||||
*
|
||||
* Creates a JWT in a single step, from the format string and args through to
|
||||
* outputting a well-formed compact JWT representation in out. The provided
|
||||
* JOSE header's syntax is checked before it is added to the JWT.
|
||||
*
|
||||
* Returns 0 if all is well and *out_len is the amount of data in out, else
|
||||
* nonzero if failed. Temp must be large enough to hold various intermediate
|
||||
* representations.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwt_sign_via_info(struct lws_context *ctx, struct lws_jwk *jwk,
|
||||
const struct lws_jwt_sign_info *info, const char *format, ...) LWS_FORMAT(4);
|
||||
|
||||
/**
|
||||
* lws_jwt_token_sanity() - check a validated jwt payload for sanity
|
||||
*
|
||||
* \param in: the JWT payload
|
||||
* \param in_len: the length of the JWT payload
|
||||
* \param iss: the expected issuer of the token
|
||||
* \param aud: the expected audience of the token
|
||||
* \param csrf_in: NULL, or the csrf token that came in on a URL
|
||||
* \param sub: a buffer to hold the subject name in the JWT (eg, account name)
|
||||
* \param sub_len: the max length of the sub buffer
|
||||
* \param secs_left: set to the number of seconds of valid auth left if valid
|
||||
*
|
||||
* This performs some generic sanity tests on validated JWT payload...
|
||||
*
|
||||
* - the issuer is as expected
|
||||
* - the audience is us
|
||||
* - current time is OK for nbf ("not before") in the token
|
||||
* - current time is OK for exp ("expiry") in the token
|
||||
* - if csrf_in is not NULL, that the JWK has a csrf and it matches it
|
||||
* - if sub is not NULL, that the JWK provides a subject (and copies it to sub)
|
||||
*
|
||||
* If the tests pass, *secs_left is set to the number of remaining seconds the
|
||||
* auth is valid.
|
||||
*
|
||||
* Returns 0 if no inconsistency, else nonzero.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwt_token_sanity(const char *in, size_t in_len,
|
||||
const char *iss, const char *aud, const char *csrf_in,
|
||||
char *sub, size_t sub_len, unsigned long *exp_unix_time);
|
||||
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
|
||||
struct lws_jwt_sign_set_cookie {
|
||||
struct lws_jwk *jwk;
|
||||
/**< entry: required signing key */
|
||||
const char *alg;
|
||||
/**< entry: required signing alg, eg, "ES512" */
|
||||
const char *iss;
|
||||
/**< entry: issuer name to use */
|
||||
const char *aud;
|
||||
/**< entry: audience */
|
||||
const char *cookie_name;
|
||||
/**< entry: the name of the cookie */
|
||||
char sub[33];
|
||||
/**< sign-entry, validate-exit: subject */
|
||||
const char *extra_json;
|
||||
/**< sign-entry, validate-exit:
|
||||
* optional "ext" JSON object contents for the JWT */
|
||||
size_t extra_json_len;
|
||||
/**< validate-exit:
|
||||
* length of optional "ext" JSON object contents for the JWT */
|
||||
const char *csrf_in;
|
||||
/**< validate-entry:
|
||||
* NULL, or an external CSRF token to check against what is in the JWT */
|
||||
unsigned long expiry_unix_time;
|
||||
/**< sign-entry: seconds the JWT and cookie may live,
|
||||
* validate-exit: expiry unix time */
|
||||
};
|
||||
|
||||
/**
|
||||
* lws_jwt_sign_token_set_cookie() - creates sets a JWT in a wsi cookie
|
||||
*
|
||||
* \param wsi: the wsi to create the cookie header on
|
||||
* \param i: structure describing what should be in the JWT
|
||||
* \param p: wsi headers area
|
||||
* \param end: end of wsi headers area
|
||||
*
|
||||
* Creates a JWT specified \p i, and attaches it to the outgoing headers on
|
||||
* wsi. Returns 0 if successful.
|
||||
*
|
||||
* Best-practice security restrictions are applied to the cookie set action,
|
||||
* including forcing httponly, and __Host- prefix. As required by __Host-, the
|
||||
* cookie Path is set to /. __Host- is applied by the function, the cookie_name
|
||||
* should just be "xyz" for "__Host-xyz".
|
||||
*
|
||||
* \p extra_json should just be the bare JSON, a { } is provided around it by
|
||||
* the function if it's non-NULL. For example, "\"authorization\": 1".
|
||||
*
|
||||
* It's recommended the secs parameter is kept as small as consistent with one
|
||||
* user session on the site if possible, eg, 10 minutes or 20 minutes. At the
|
||||
* server, it can determine how much time is left in the auth and inform the
|
||||
* client; if the JWT validity expires, the page should reload so the UI always
|
||||
* reflects what's possible to do with the authorization state correctly. If
|
||||
* the JWT expires, the user can log back in using credentials usually stored in
|
||||
* the browser and auto-filled-in, so this is not very inconvenient.
|
||||
*
|
||||
* This is a helper on top of the other JOSE and JWT apis that somewhat crosses
|
||||
* over between JWT and HTTP, since it knows about cookies. So it is only built
|
||||
* if both LWS_WITH_JOSE and one of the http-related roles enabled.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwt_sign_token_set_http_cookie(struct lws *wsi,
|
||||
const struct lws_jwt_sign_set_cookie *i,
|
||||
uint8_t **p, uint8_t *end);
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_jwt_get_http_cookie_validate_jwt(struct lws *wsi,
|
||||
struct lws_jwt_sign_set_cookie *i,
|
||||
char *out, size_t *out_len);
|
||||
#endif
|
||||
|
||||
///@}
|
||||
|
|
@ -1,542 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup lecp CBOR parser
|
||||
* ##CBOR parsing related functions
|
||||
* \ingroup lwsapi
|
||||
*
|
||||
* LECP is an extremely lightweight CBOR stream parser included in lws. It
|
||||
* is aligned in approach with the LEJP JSON stream parser, with some additional
|
||||
* things needed for CBOR.
|
||||
*/
|
||||
//@{
|
||||
|
||||
#ifndef LECP_MAX_PARSING_STACK_DEPTH
|
||||
#define LECP_MAX_PARSING_STACK_DEPTH 5
|
||||
#endif
|
||||
#ifndef LECP_MAX_DEPTH
|
||||
#define LECP_MAX_DEPTH 12
|
||||
#endif
|
||||
#ifndef LECP_MAX_INDEX_DEPTH
|
||||
#define LECP_MAX_INDEX_DEPTH 8
|
||||
#endif
|
||||
#ifndef LECP_MAX_PATH
|
||||
#define LECP_MAX_PATH 128
|
||||
#endif
|
||||
#ifndef LECP_STRING_CHUNK
|
||||
/* must be >= 30 to assemble floats */
|
||||
#define LECP_STRING_CHUNK 254
|
||||
#endif
|
||||
|
||||
#define LECP_FLAG_CB_IS_VALUE 64
|
||||
|
||||
/*
|
||||
* CBOR initial byte 3 x MSB bits are these
|
||||
*/
|
||||
|
||||
enum {
|
||||
LWS_CBOR_MAJTYP_UINT = 0 << 5,
|
||||
LWS_CBOR_MAJTYP_INT_NEG = 1 << 5,
|
||||
LWS_CBOR_MAJTYP_BSTR = 2 << 5,
|
||||
LWS_CBOR_MAJTYP_TSTR = 3 << 5,
|
||||
LWS_CBOR_MAJTYP_ARRAY = 4 << 5,
|
||||
LWS_CBOR_MAJTYP_MAP = 5 << 5,
|
||||
LWS_CBOR_MAJTYP_TAG = 6 << 5,
|
||||
LWS_CBOR_MAJTYP_FLOAT = 7 << 5, /* also BREAK */
|
||||
|
||||
LWS_CBOR_MAJTYP_MASK = 7 << 5,
|
||||
|
||||
/*
|
||||
* For the low 5 bits of the opcode, 0-23 are literals, unless it's
|
||||
* FLOAT.
|
||||
*
|
||||
* 24 = 1 byte; 25 = 2..., 26 = 4... and 27 = 8 bytes following literal.
|
||||
*/
|
||||
LWS_CBOR_1 = 24,
|
||||
LWS_CBOR_2 = 25,
|
||||
LWS_CBOR_4 = 26,
|
||||
LWS_CBOR_8 = 27,
|
||||
|
||||
LWS_CBOR_RESERVED = 28,
|
||||
|
||||
LWS_CBOR_SUBMASK = 0x1f,
|
||||
|
||||
/*
|
||||
* Major type 7 discriminators in low 5 bits
|
||||
* 0 - 23 is SIMPLE implicit value (like, eg, LWS_CBOR_SWK_TRUE)
|
||||
*/
|
||||
LWS_CBOR_SWK_FALSE = 20,
|
||||
LWS_CBOR_SWK_TRUE = 21,
|
||||
LWS_CBOR_SWK_NULL = 22,
|
||||
LWS_CBOR_SWK_UNDEFINED = 23,
|
||||
|
||||
LWS_CBOR_M7_SUBTYP_SIMPLE_X8 = 24, /* simple with additional byte */
|
||||
LWS_CBOR_M7_SUBTYP_FLOAT16 = 25,
|
||||
LWS_CBOR_M7_SUBTYP_FLOAT32 = 26,
|
||||
LWS_CBOR_M7_SUBTYP_FLOAT64 = 27,
|
||||
LWS_CBOR_M7_BREAK = 31,
|
||||
|
||||
/* 28, 29, 30 are illegal.
|
||||
*
|
||||
* 31 is illegal for UINT, INT_NEG, and TAG;
|
||||
* for BSTR, TSTR, ARRAY and MAP it means "indefinite length", ie,
|
||||
* it's made up of an endless amount of determinite-length
|
||||
* fragments terminated with a BREAK (FLOAT | 31) instead of the
|
||||
* next determinite-length fragment. The second framing level
|
||||
* means no need for escapes for BREAK in the data.
|
||||
*/
|
||||
|
||||
LWS_CBOR_INDETERMINITE = 31,
|
||||
|
||||
/*
|
||||
* Well-known tags
|
||||
*/
|
||||
|
||||
LWS_CBOR_WKTAG_DATETIME_STD = 0, /* text */
|
||||
LWS_CBOR_WKTAG_DATETIME_EPOCH = 1, /* int or float */
|
||||
LWS_CBOR_WKTAG_BIGNUM_UNSIGNED = 2, /* byte string */
|
||||
LWS_CBOR_WKTAG_BIGNUM_NEGATIVE = 3, /* byte string */
|
||||
LWS_CBOR_WKTAG_DECIMAL_FRAC = 4, /* array */
|
||||
LWS_CBOR_WKTAG_BIGFLOAT = 5, /* array */
|
||||
|
||||
LWS_CBOR_WKTAG_COSE_ENC0 = 16,
|
||||
LWS_CBOR_WKTAG_COSE_MAC0 = 17,
|
||||
LWS_CBOR_WKTAG_COSE_SIGN1 = 18,
|
||||
|
||||
LWS_CBOR_WKTAG_TO_B64U = 21, /* any */
|
||||
LWS_CBOR_WKTAG_TO_B64 = 22, /* any */
|
||||
LWS_CBOR_WKTAG_TO_B16 = 23, /* any */
|
||||
LWS_CBOR_WKTAG_CBOR = 24, /* byte string */
|
||||
|
||||
LWS_CBOR_WKTAG_URI = 32, /* text string */
|
||||
LWS_CBOR_WKTAG_B64U = 33, /* text string */
|
||||
LWS_CBOR_WKTAG_B64 = 34, /* text string */
|
||||
LWS_CBOR_WKTAG_MIME = 36, /* text string */
|
||||
|
||||
LWS_CBOR_WKTAG_COSE_ENC = 96,
|
||||
LWS_CBOR_WKTAG_COSE_MAC = 97,
|
||||
LWS_CBOR_WKTAG_COSE_SIGN = 98,
|
||||
|
||||
LWS_CBOR_WKTAG_SELFDESCCBOR = 55799
|
||||
};
|
||||
|
||||
enum lecp_callbacks {
|
||||
LECPCB_CONSTRUCTED = 0,
|
||||
LECPCB_DESTRUCTED = 1,
|
||||
|
||||
LECPCB_COMPLETE = 3,
|
||||
LECPCB_FAILED = 4,
|
||||
|
||||
LECPCB_PAIR_NAME = 5,
|
||||
|
||||
LECPCB_VAL_TRUE = LECP_FLAG_CB_IS_VALUE | 6,
|
||||
LECPCB_VAL_FALSE = LECP_FLAG_CB_IS_VALUE | 7,
|
||||
LECPCB_VAL_NULL = LECP_FLAG_CB_IS_VALUE | 8,
|
||||
LECPCB_VAL_NUM_INT = LECP_FLAG_CB_IS_VALUE | 9,
|
||||
LECPCB_VAL_RESERVED = LECP_FLAG_CB_IS_VALUE | 10,
|
||||
LECPCB_VAL_STR_START = 11, /* notice handle separately */
|
||||
LECPCB_VAL_STR_CHUNK = LECP_FLAG_CB_IS_VALUE | 12,
|
||||
LECPCB_VAL_STR_END = LECP_FLAG_CB_IS_VALUE | 13,
|
||||
|
||||
LECPCB_ARRAY_START = 14,
|
||||
LECPCB_ARRAY_END = 15,
|
||||
|
||||
LECPCB_OBJECT_START = 16,
|
||||
LECPCB_OBJECT_END = 17,
|
||||
|
||||
LECPCB_TAG_START = 18,
|
||||
LECPCB_TAG_END = 19,
|
||||
|
||||
LECPCB_VAL_NUM_UINT = LECP_FLAG_CB_IS_VALUE | 20,
|
||||
LECPCB_VAL_UNDEFINED = LECP_FLAG_CB_IS_VALUE | 21,
|
||||
LECPCB_VAL_FLOAT16 = LECP_FLAG_CB_IS_VALUE | 22,
|
||||
LECPCB_VAL_FLOAT32 = LECP_FLAG_CB_IS_VALUE | 23,
|
||||
LECPCB_VAL_FLOAT64 = LECP_FLAG_CB_IS_VALUE | 24,
|
||||
|
||||
LECPCB_VAL_SIMPLE = LECP_FLAG_CB_IS_VALUE | 25,
|
||||
|
||||
LECPCB_VAL_BLOB_START = 26, /* notice handle separately */
|
||||
LECPCB_VAL_BLOB_CHUNK = LECP_FLAG_CB_IS_VALUE | 27,
|
||||
LECPCB_VAL_BLOB_END = LECP_FLAG_CB_IS_VALUE | 28,
|
||||
|
||||
LECPCB_ARRAY_ITEM_START = 29,
|
||||
LECPCB_ARRAY_ITEM_END = 30,
|
||||
|
||||
LECPCB_LITERAL_CBOR = 31,
|
||||
};
|
||||
|
||||
enum lecp_reasons {
|
||||
LECP_CONTINUE = -1,
|
||||
LECP_REJECT_BAD_CODING = -2,
|
||||
LECP_REJECT_UNKNOWN = -3,
|
||||
LECP_REJECT_CALLBACK = -4,
|
||||
LECP_STACK_OVERFLOW = -5,
|
||||
};
|
||||
|
||||
|
||||
struct lecp_item {
|
||||
union {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
|
||||
uint64_t u32;
|
||||
|
||||
uint16_t hf;
|
||||
#if defined(LWS_WITH_CBOR_FLOAT)
|
||||
float f;
|
||||
double d;
|
||||
#else
|
||||
uint32_t f;
|
||||
uint64_t d;
|
||||
#endif
|
||||
} u;
|
||||
uint8_t opcode;
|
||||
};
|
||||
|
||||
struct lecp_ctx;
|
||||
typedef signed char (*lecp_callback)(struct lecp_ctx *ctx, char reason);
|
||||
|
||||
struct _lecp_stack {
|
||||
char s; /* lejp_state stack*/
|
||||
uint8_t p; /* path length */
|
||||
char i; /* index array length */
|
||||
char indet; /* indeterminite */
|
||||
char intermediate; /* in middle of string */
|
||||
|
||||
char pop_iss;
|
||||
uint64_t tag;
|
||||
uint64_t collect_rem;
|
||||
uint32_t ordinal;
|
||||
uint8_t opcode;
|
||||
uint8_t send_new_array_item;
|
||||
uint8_t barrier;
|
||||
};
|
||||
|
||||
struct _lecp_parsing_stack {
|
||||
void *user; /* private to the stack level */
|
||||
lecp_callback cb;
|
||||
const char * const *paths;
|
||||
uint8_t count_paths;
|
||||
uint8_t ppos;
|
||||
uint8_t path_match;
|
||||
};
|
||||
|
||||
struct lecp_ctx {
|
||||
|
||||
/* sorted by type for most compact alignment
|
||||
*
|
||||
* pointers
|
||||
*/
|
||||
void *user;
|
||||
uint8_t *collect_tgt;
|
||||
|
||||
/* arrays */
|
||||
|
||||
struct _lecp_parsing_stack pst[LECP_MAX_PARSING_STACK_DEPTH];
|
||||
struct _lecp_stack st[LECP_MAX_DEPTH];
|
||||
uint16_t i[LECP_MAX_INDEX_DEPTH]; /* index array */
|
||||
uint16_t wild[LECP_MAX_INDEX_DEPTH]; /* index array */
|
||||
char path[LECP_MAX_PATH];
|
||||
uint8_t cbor[64]; /* literal cbor capture */
|
||||
|
||||
struct lecp_item item;
|
||||
|
||||
|
||||
/* size_t */
|
||||
|
||||
size_t path_stride; /* 0 means default ptr size, else
|
||||
* stride... allows paths to be
|
||||
* provided composed inside a
|
||||
* larger user struct instead of a
|
||||
* duplicated array */
|
||||
size_t used_in; /* bytes of input consumed */
|
||||
|
||||
/* short */
|
||||
|
||||
uint16_t uni;
|
||||
|
||||
/* char */
|
||||
|
||||
uint8_t npos;
|
||||
uint8_t dcount;
|
||||
uint8_t f;
|
||||
uint8_t sp; /* stack head */
|
||||
uint8_t ipos; /* index stack depth */
|
||||
uint8_t count_paths;
|
||||
uint8_t path_match;
|
||||
uint8_t path_match_len;
|
||||
uint8_t wildcount;
|
||||
uint8_t pst_sp; /* parsing stack head */
|
||||
uint8_t outer_array;
|
||||
uint8_t cbor_pos;
|
||||
uint8_t literal_cbor_report;
|
||||
char present; /* temp for cb reason to use */
|
||||
|
||||
uint8_t be; /* big endian */
|
||||
|
||||
/* at end so we can memset the rest of it */
|
||||
|
||||
char buf[LECP_STRING_CHUNK + 1];
|
||||
};
|
||||
|
||||
struct lws_lec_pctx;
|
||||
typedef struct lws_lec_pctx lws_lec_pctx_t;
|
||||
|
||||
enum lws_lec_pctx_ret {
|
||||
LWS_LECPCTX_RET_FINISHED = 0,
|
||||
LWS_LECPCTX_RET_AGAIN, /* call again to continue writing buffer */
|
||||
LWS_LECPCTX_RET_FAIL /* something broken, eg, format string */
|
||||
};
|
||||
|
||||
enum cbp_state {
|
||||
CBPS_IDLE,
|
||||
CBPS_PC1,
|
||||
CBPS_PC2,
|
||||
CBPS_PC3,
|
||||
|
||||
CBPS_STRING_BODY,
|
||||
|
||||
CBPS_NUM_LIT,
|
||||
|
||||
CBPS_STRING_LIT,
|
||||
|
||||
CBPS_CONTYPE,
|
||||
};
|
||||
|
||||
typedef struct lws_lec_pctx {
|
||||
uint8_t stack[16];
|
||||
uint8_t vaa[16];
|
||||
uint8_t indet[16];
|
||||
uint8_t scratch[24];
|
||||
uint8_t *start; /* the beginning of the out buf */
|
||||
uint8_t *buf; /* cur pos in output buf */
|
||||
uint8_t *end; /* the end of the output buf */
|
||||
|
||||
const uint8_t *ongoing_src;
|
||||
uint64_t ongoing_len;
|
||||
uint64_t ongoing_done;
|
||||
|
||||
struct lecp_item item;
|
||||
|
||||
size_t used; /* number of bytes valid from start */
|
||||
|
||||
int opaque[4]; /* ignored by lws, caller may use */
|
||||
|
||||
enum cbp_state state;
|
||||
unsigned int fmt_pos;
|
||||
uint8_t sp;
|
||||
uint8_t scratch_len;
|
||||
uint8_t escflag;
|
||||
uint8_t _long;
|
||||
uint8_t vaa_pos;
|
||||
uint8_t dotstar;
|
||||
} lws_lec_pctx_t;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_lec_int(lws_lec_pctx_t *ctx, uint8_t opcode, uint8_t indet, uint64_t num);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_lec_scratch(lws_lec_pctx_t *ctx);
|
||||
|
||||
/*
|
||||
* lws_lec_init() - prepare a cbor writing context
|
||||
*
|
||||
* \param ctx: the cbor writing context to prepare
|
||||
* \param buf: the output buffer start
|
||||
* \param len: the amount of the output buffer we can use
|
||||
*
|
||||
* Prepares a cbor writing context so that les_lec_printf can be used to
|
||||
* write into it.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_lec_init(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len);
|
||||
|
||||
/*
|
||||
* lws_lec_setbuf() - update the output buffer for an initialized cbor writing ctx
|
||||
*
|
||||
* \param ctx: the cbor writing context to prepare
|
||||
* \param buf: the output buffer start
|
||||
* \param len: the amount of the output buffer we can use
|
||||
*
|
||||
* Leaves the cbor writing context state as it is, but resets the output buffer
|
||||
* it writes into as given in \p buf and \p len
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_lec_setbuf(lws_lec_pctx_t *ctx, uint8_t *buf, size_t len);
|
||||
|
||||
/*
|
||||
* lws_lec_vsprintf() - write into a cbor writing context
|
||||
*
|
||||
* \param ctx: the cbor writing context to prepare
|
||||
* \param format: a printf style argument map
|
||||
* \param args: the va args
|
||||
*
|
||||
* CBOR-aware vsprintf which pauses output when it fills the output buffer. You
|
||||
* can call it again with the same args and same lws_lex_pctx to resume filling
|
||||
*
|
||||
* Returns either LWS_LECPCTX_RET_FINISHED if we have nothing left over that we
|
||||
* want to put in the buffer, or LWS_LECPCTX_RET_AGAIN if the function should
|
||||
* be called again with the same arguments (perhaps into a different output
|
||||
* buffer) to continue emitting output from where it left off.
|
||||
*
|
||||
* If LWS_LECPCTX_RET_AGAIN is returned, lws_lec_setbuf() must be used on the
|
||||
* context to reset or change the output buffer before calling again.
|
||||
*
|
||||
* The number of bytes placed in the output buffer is available in ctx->used.
|
||||
*
|
||||
* \p format is a printf-type format string that is specialized for CBOR
|
||||
* generation. It understands the following specifiers
|
||||
*
|
||||
* |`123`||unsigned literal number|
|
||||
* |`-123`||signed literal number|
|
||||
* |`%u`|`unsigned int`|number|
|
||||
* |`%lu`|`unsigned long int`|number|
|
||||
* |`%llu`|`unsigned long long int`|number|
|
||||
* |`%d`|`signed int`|number|
|
||||
* |`%ld`|`signed long int`|number|
|
||||
* |`%lld`|`signed long long int`|number|
|
||||
* |`%f`|`double`|floating point number|
|
||||
* |`123(...)`||literal tag and scope|
|
||||
* |`%t(...)`|`unsigned int`|tag and scope|
|
||||
* |`%lt(...)`|`unsigned long int`|tag and scope|
|
||||
* |`%llt(...)`|`unsigned long long int`|tag and scope|
|
||||
* |`[...]`||Array (fixed len if `]` in same format string)|
|
||||
* |`{...}`||Map (fixed len if `}` in same format string)|
|
||||
* |`<t...>`||Container for indeterminite text string frags|
|
||||
* |`<b...>`||Container for indeterminite binary string frags|
|
||||
* |`'string'`||Literal text of known length|
|
||||
* |`%s`|`const char *`|NUL-terminated string|
|
||||
* |`%.*s`|`int`, `const char *`|length-specified string|
|
||||
* |`%.*b`|`int`, `const uint8_t *`|length-specified binary|
|
||||
* |`:`||separator between Map items (a:b)|
|
||||
* |`,`||separator between Map pairs or array items|
|
||||
*
|
||||
* See READMEs/README.cbor-lecp.md for more details.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret
|
||||
lws_lec_vsprintf(lws_lec_pctx_t *ctx, const char *format, va_list args);
|
||||
|
||||
/*
|
||||
* lws_lec_printf() - write into a cbor writing context
|
||||
*
|
||||
* \param ctx: the cbor writing context to prepare
|
||||
* \param format: a printf style argument map
|
||||
* \param ...: format args
|
||||
*
|
||||
* See lws_lec_vsprintf() for format details. This is the most common way
|
||||
* to format the CBOR output.
|
||||
*
|
||||
* See READMEs/README.cbor-lecp.md for more details.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN enum lws_lec_pctx_ret
|
||||
lws_lec_printf(lws_lec_pctx_t *ctx, const char *format, ...);
|
||||
|
||||
/**
|
||||
* lecp_construct() - Construct an LECP parser context
|
||||
*
|
||||
* \param ctx: the parser context object to be initialized
|
||||
* \param cb: the user callback to receive the parsing events
|
||||
* \param user: an opaque user pointer available at \p cb
|
||||
* \param paths: an optional array of parsing paths
|
||||
* \param paths_count: how many paths in \p paths
|
||||
*
|
||||
* Prepares an LECP parser context for parsing.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lecp_construct(struct lecp_ctx *ctx, lecp_callback cb, void *user,
|
||||
const char * const *paths, unsigned char paths_count);
|
||||
|
||||
/**
|
||||
* lecp_destruct() - Destroys an LECP parser context
|
||||
*
|
||||
* \param ctx: the parser context object to be destroyed
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lecp_destruct(struct lecp_ctx *ctx);
|
||||
|
||||
/**
|
||||
* lecp_parse() - parses a chunk of input CBOR
|
||||
*
|
||||
* \p ctx: the parsing context
|
||||
* \p cbor: the start of the chunk of CBOR
|
||||
* \p len: the number of bytes of CBOR available at \p cbor
|
||||
*
|
||||
* Returns LECP_CONTINUE if more input needed, one of enum lecp_reasons for a
|
||||
* fatal error, else 0 for successful parsing completion.
|
||||
*
|
||||
* On success or _CONTINUE, ctx->used_in is set to the number of input bytes
|
||||
* consumed.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lecp_parse(struct lecp_ctx *ctx, const uint8_t *cbor, size_t len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lecp_change_callback(struct lecp_ctx *ctx, lecp_callback cb);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const char *
|
||||
lecp_error_to_string(int e);
|
||||
|
||||
/**
|
||||
* lecp_parse_report_raw() - turn cbor raw reporting on and off
|
||||
*
|
||||
* \param ctx: the lecp context
|
||||
* \param on: 0 to disable (defaults disabled), 1 to enable
|
||||
*
|
||||
* For cose_sign, it needs access to raw cbor subtrees for the hash input.
|
||||
* This api causes LECPCB_LITERAL_CBOR parse callbacks when there are
|
||||
* ctx->cbor_pos bytes of raw cbor available in ctx->cbor[]. the callbacks
|
||||
* occur when the ctx->cbor[] buffer fills or if it holds anything when this
|
||||
* spi is used to stop the reports.
|
||||
*
|
||||
* The same CBOR that is being captured continues to be passed for parsing.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lecp_parse_report_raw(struct lecp_ctx *ctx, int on);
|
||||
|
||||
/**
|
||||
* lecp_parse_map_is_key() - return nonzero if we're in a map and this is a key
|
||||
*
|
||||
* \param ctx: the lwcp context
|
||||
*
|
||||
* Checks if the current value is a key in a map, ie, that you are on a "key" in
|
||||
* a list of "{key: value}" pairs. Zero means you're either not in a map or not
|
||||
* on the key part, and nonzero means you are in a map and on a key part.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lecp_parse_map_is_key(struct lecp_ctx *ctx);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lecp_parse_subtree(struct lecp_ctx *ctx, const uint8_t *in, size_t len);
|
||||
|
||||
/*
|
||||
* Helpers for half-float
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_singles2halfp(uint16_t *hp, uint32_t x);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_halfp2singles(uint32_t *xp, uint16_t h);
|
||||
|
||||
//@}
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Generic LED controller ops
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* This is like an abstract class for leds, a real implementation provides
|
||||
* functions for the ops that use the underlying, eg, OS gpio arrangements.
|
||||
*/
|
||||
|
||||
/* only b15 significant for GPIO */
|
||||
typedef uint16_t lws_led_intensity_t;
|
||||
typedef uint16_t lws_led_seq_phase_t;
|
||||
|
||||
/* the normalized max intensity */
|
||||
#define LWS_LED_MAX_INTENSITY (0xffff)
|
||||
|
||||
/* the normalized 360 degree phase count for intensity functions */
|
||||
#define LWS_LED_FUNC_PHASE 65536
|
||||
/* used when the sequence doesn't stop by itself and goes around forever */
|
||||
#define LWS_SEQ_LEDPHASE_TOTAL_ENDLESS (-1)
|
||||
|
||||
#define LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS 33
|
||||
|
||||
struct lws_led_state; /* opaque */
|
||||
struct lws_pwm_ops; /* forward ref */
|
||||
|
||||
typedef lws_led_intensity_t (*lws_led_lookup_t)(lws_led_seq_phase_t ph);
|
||||
|
||||
typedef struct lws_led_sequence_def_t {
|
||||
lws_led_lookup_t func;
|
||||
lws_led_seq_phase_t ledphase_offset;
|
||||
int ledphase_total; /* 65536= one cycle */
|
||||
uint16_t ms;
|
||||
uint8_t flags;
|
||||
} lws_led_sequence_def_t;
|
||||
|
||||
enum {
|
||||
LLSI_CURR,
|
||||
LLSI_NEXT,
|
||||
LLSI_TRANS
|
||||
};
|
||||
|
||||
typedef struct lws_led_state_ch
|
||||
{
|
||||
const lws_led_sequence_def_t *seq; /* NULL = inactive */
|
||||
lws_led_seq_phase_t ph;
|
||||
lws_led_seq_phase_t step;
|
||||
int phase_budget;
|
||||
lws_led_intensity_t last;
|
||||
/**< at the end of the sequence we decouple the sequencer, but leave
|
||||
* the last computed sample behind for further transitions to base off
|
||||
*/
|
||||
} lws_led_state_ch_t;
|
||||
|
||||
typedef struct lws_led_state_chs
|
||||
{
|
||||
lws_led_state_ch_t seqs[3];
|
||||
} lws_led_state_chs_t;
|
||||
|
||||
/* this should always be first in the subclassed implementation types */
|
||||
|
||||
typedef struct lws_led_ops {
|
||||
void (*intensity)(const struct lws_led_ops *lo, const char *name,
|
||||
lws_led_intensity_t inten);
|
||||
/**< for BOOL led control like GPIO, only inten b15 is significant */
|
||||
struct lws_led_state * (*create)(const struct lws_led_ops *led_ops);
|
||||
void (*destroy)(struct lws_led_state *);
|
||||
} lws_led_ops_t;
|
||||
|
||||
typedef struct lws_led_gpio_map {
|
||||
const char *name;
|
||||
_lws_plat_gpio_t gpio;
|
||||
lws_led_lookup_t intensity_correction;
|
||||
/**< May be NULL. If GPIO-based LED, ignored. If pwm_ops provided,
|
||||
* NULL means use default CIE 100% correction function. If non-NULL,
|
||||
* use the pointed-to correction function. This is useful to provide
|
||||
* LED-specific intensity correction / scaling so different types of
|
||||
* LED can "look the same". */
|
||||
const struct lws_pwm_ops *pwm_ops;
|
||||
/**< if NULL, gpio controls the led directly. If set to a pwm_ops,
|
||||
* the led control is outsourced to the pwm controller. */
|
||||
uint8_t active_level;
|
||||
} lws_led_gpio_map_t;
|
||||
|
||||
typedef struct lws_led_gpio_controller {
|
||||
const lws_led_ops_t led_ops;
|
||||
|
||||
const lws_gpio_ops_t *gpio_ops;
|
||||
const lws_led_gpio_map_t *led_map;
|
||||
uint8_t count_leds;
|
||||
} lws_led_gpio_controller_t;
|
||||
|
||||
/* ops */
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_led_state *
|
||||
lws_led_gpio_create(const lws_led_ops_t *led_ops);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_led_gpio_destroy(struct lws_led_state *lcs);
|
||||
|
||||
/**
|
||||
* lws_led_gpio_intensity() - set the static intensity of an led
|
||||
*
|
||||
* \param lo: the base class of the led controller
|
||||
* \param index: which led in the controller set
|
||||
* \param inten: 16-bit unsigned intensity
|
||||
*
|
||||
* For LEDs controlled by a BOOL like GPIO, only inten b15 is significant.
|
||||
* For PWM type LED control, as many bits as the hardware can support from b15
|
||||
* down are significant.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name,
|
||||
lws_led_intensity_t inten);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_led_transition(struct lws_led_state *lcs, const char *name,
|
||||
const lws_led_sequence_def_t *next,
|
||||
const lws_led_sequence_def_t *trans);
|
||||
|
||||
|
||||
#define lws_led_gpio_ops \
|
||||
{ \
|
||||
.create = lws_led_gpio_create, \
|
||||
.destroy = lws_led_gpio_destroy, \
|
||||
.intensity = lws_led_gpio_intensity, \
|
||||
}
|
||||
|
||||
|
|
@ -1,786 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup log Logging
|
||||
*
|
||||
* ##Logging
|
||||
*
|
||||
* Lws provides flexible and filterable logging facilities, which can be
|
||||
* used inside lws and in user code.
|
||||
*
|
||||
* Log categories may be individually filtered bitwise, and directed to built-in
|
||||
* sinks for syslog-compatible logging, or a user-defined function.
|
||||
*
|
||||
* Traditional logs use a single, processwide logging context. New style log
|
||||
* apis (lws_xxx_cx()) can pass the logging context to use in.
|
||||
*/
|
||||
///@{
|
||||
|
||||
#define LLL_ERR (1 << 0)
|
||||
#define LLL_WARN (1 << 1)
|
||||
#define LLL_NOTICE (1 << 2)
|
||||
#define LLL_INFO (1 << 3)
|
||||
#define LLL_DEBUG (1 << 4)
|
||||
#define LLL_PARSER (1 << 5)
|
||||
#define LLL_HEADER (1 << 6)
|
||||
#define LLL_EXT (1 << 7)
|
||||
#define LLL_CLIENT (1 << 8)
|
||||
#define LLL_LATENCY (1 << 9)
|
||||
#define LLL_USER (1 << 10)
|
||||
#define LLL_THREAD (1 << 11)
|
||||
|
||||
#define LLL_COUNT (12) /* set to count of valid flags */
|
||||
|
||||
#define LLLF_SECRECY_PII (1 << 16)
|
||||
/**< contains Personally Identifiable Information */
|
||||
#define LLLF_SECRECY_BEARER (1 << 17)
|
||||
/**< possession of this data allows impersonation */
|
||||
|
||||
#define LLLF_LOG_TIMESTAMP (1 << 18)
|
||||
/**< set to prepend logs with timestamp */
|
||||
|
||||
#define LLLF_LOG_CONTEXT_AWARE (1 << 30)
|
||||
/**< set if the context uses an emit function that takes the logctx, auto-
|
||||
* applied when setting emit using lws_set_log_level_cx() api */
|
||||
|
||||
struct lws_log_cx;
|
||||
|
||||
typedef void (*lws_log_emit_t)(int level, const char *line);
|
||||
typedef void (*lws_log_emit_cx_t)(struct lws_log_cx *cx, int level,
|
||||
const char *line, size_t len);
|
||||
typedef void (*lws_log_prepend_cx_t)(struct lws_log_cx *cx, void *obj,
|
||||
char **p, char *e);
|
||||
typedef void (*lws_log_use_cx_t)(struct lws_log_cx *cx, int _new);
|
||||
|
||||
/*
|
||||
* This is the logging context
|
||||
*/
|
||||
|
||||
typedef struct lws_log_cx {
|
||||
union {
|
||||
lws_log_emit_t emit; /* legacy emit function */
|
||||
lws_log_emit_cx_t emit_cx; /* LLLF_LOG_CONTEXT_AWARE */
|
||||
} u;
|
||||
lws_log_use_cx_t refcount_cb;
|
||||
/**< NULL, or a function called after each change to .refcount below,
|
||||
* this enables implementing side-effects like opening and closing
|
||||
* log files when the first and last object binds / unbinds */
|
||||
lws_log_prepend_cx_t prepend;
|
||||
/**< NULL, or a cb to optionally prepend a string to logs we are a
|
||||
* parent of */
|
||||
struct lws_log_cx *parent;
|
||||
/**< NULL, or points to log ctx we are a child of */
|
||||
void *opaque;
|
||||
/**< ignored by lws, used to pass config to emit_cx, eg, filepath */
|
||||
void *stg;
|
||||
/**< ignored by lws, may be used a storage by refcount_cb / emit_cx */
|
||||
uint32_t lll_flags;
|
||||
/**< mask of log levels we want to emit in this context */
|
||||
int32_t refcount;
|
||||
/**< refcount of objects bound to this log context */
|
||||
} lws_log_cx_t;
|
||||
|
||||
/**
|
||||
* lwsl_timestamp: generate logging timestamp string
|
||||
*
|
||||
* \param level: logging level
|
||||
* \param p: char * buffer to take timestamp
|
||||
* \param len: length of p
|
||||
*
|
||||
* returns length written in p
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lwsl_timestamp(int level, char *p, size_t len);
|
||||
|
||||
#if defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)
|
||||
#define _lws_log(aaa, ...) SMSG(__VA_ARGS__)
|
||||
#else
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
_lws_log(int filter, const char *format, ...) LWS_FORMAT(2);
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
_lws_logv(int filter, const char *format, va_list vl);
|
||||
#endif
|
||||
|
||||
struct lws_vhost;
|
||||
struct lws;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_log_cx *
|
||||
lwsl_context_get_cx(struct lws_context *cx);
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_log_cx *
|
||||
lwsl_vhost_get_cx(struct lws_vhost *vh);
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_log_cx *
|
||||
lwsl_wsi_get_cx(struct lws *wsi);
|
||||
#if defined(LWS_WITH_SECURE_STREAMS)
|
||||
struct lws_ss_handle;
|
||||
struct lws_sspc_handle;
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_log_cx *
|
||||
lwsl_ss_get_cx(struct lws_ss_handle *ss);
|
||||
LWS_VISIBLE LWS_EXTERN struct lws_log_cx *
|
||||
lwsl_sspc_get_cx(struct lws_sspc_handle *ss);
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_emit_cx_file(struct lws_log_cx *cx, int level, const char *line,
|
||||
size_t len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_use_cx_file(struct lws_log_cx *cx, int _new);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_prepend_context(struct lws_log_cx *cx, void *obj, char **p, char *e);
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_prepend_vhost(struct lws_log_cx *cx, void *obj, char **p, char *e);
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_prepend_wsi(struct lws_log_cx *cx, void *obj, char **p, char *e);
|
||||
#if defined(LWS_WITH_SECURE_STREAMS)
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_prepend_ss(struct lws_log_cx *cx, void *obj, char **p, char *e);
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_log_prepend_sspc(struct lws_log_cx *cx, void *obj, char **p, char *e);
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
_lws_log_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj,
|
||||
int filter, const char *_fun, const char *format, ...) LWS_FORMAT(6);
|
||||
|
||||
#define lwsl_cx(_c, _fil, ...) \
|
||||
_lws_log_cx(lwsl_context_get_cx(_c), lws_log_prepend_context, \
|
||||
_c, _fil, __func__, __VA_ARGS__)
|
||||
#define lwsl_vhost(_v, _fil, ...) \
|
||||
_lws_log_cx(lwsl_vhost_get_cx(_v), lws_log_prepend_vhost, _v, \
|
||||
_fil, __func__, __VA_ARGS__)
|
||||
#define lwsl_wsi(_w, _fil, ...) \
|
||||
_lws_log_cx(lwsl_wsi_get_cx(_w), lws_log_prepend_wsi, _w, \
|
||||
_fil, __func__, __VA_ARGS__)
|
||||
#define lwsl_ss(_h, _fil, ...) \
|
||||
_lws_log_cx(lwsl_ss_get_cx(_h), lws_log_prepend_ss, _h, \
|
||||
_fil, __func__, __VA_ARGS__)
|
||||
|
||||
#define lwsl_hexdump_context(_c, _fil, _buf, _len) \
|
||||
lwsl_hexdump_level_cx(lwsl_context_get_cx(_c), \
|
||||
lws_log_prepend_context, \
|
||||
_c, _fil, _buf, _len)
|
||||
#define lwsl_hexdump_vhost(_v, _fil, _buf, _len) \
|
||||
lwsl_hexdump_level_cx(lwsl_vhost_get_cx(_v), \
|
||||
lws_log_prepend_vhost, \
|
||||
_v, _fil, _buf, _len)
|
||||
#define lwsl_hexdump_wsi(_w, _fil, _buf, _len) \
|
||||
lwsl_hexdump_level_cx(lwsl_wsi_get_cx(_w), \
|
||||
lws_log_prepend_wsi, \
|
||||
_w, _fil, _buf, _len)
|
||||
#define lwsl_hexdump_ss(_h, _fil, _buf, _len) \
|
||||
lwsl_hexdump_level_cx(lwsl_ss_get_cx(_h), \
|
||||
lws_log_prepend_ss, \
|
||||
_h, _fil, _buf, _len)
|
||||
|
||||
/*
|
||||
* Figure out which logs to build in or not
|
||||
*/
|
||||
|
||||
#if defined(_DEBUG)
|
||||
/*
|
||||
* In DEBUG build, select all logs unless NO_LOGS
|
||||
*/
|
||||
#if defined(LWS_WITH_NO_LOGS)
|
||||
#define _LWS_LINIT (LLL_ERR | LLL_USER)
|
||||
#else
|
||||
#define _LWS_LINIT ((1 << LLL_COUNT) - 1)
|
||||
#endif
|
||||
#else /* not _DEBUG */
|
||||
#if defined(LWS_WITH_NO_LOGS)
|
||||
#define _LWS_LINIT (LLL_ERR | LLL_USER)
|
||||
#else
|
||||
#define _LWS_LINIT (LLL_ERR | LLL_USER | LLL_WARN | LLL_NOTICE)
|
||||
#endif
|
||||
#endif /* _DEBUG */
|
||||
|
||||
/*
|
||||
* Create either empty overrides or the ones forced at build-time.
|
||||
* These overrides have the final say... any bits set in
|
||||
* LWS_LOGGING_BITFIELD_SET force the build of those logs, any bits
|
||||
* set in LWS_LOGGING_BITFIELD_CLEAR disable the build of those logs.
|
||||
*
|
||||
* If not defined lws decides based on CMAKE_BUILD_TYPE=DEBUG or not
|
||||
*/
|
||||
|
||||
#if defined(LWS_LOGGING_BITFIELD_SET)
|
||||
#define _LWS_LBS (LWS_LOGGING_BITFIELD_SET)
|
||||
#else
|
||||
#define _LWS_LBS 0
|
||||
#endif
|
||||
|
||||
#if defined(LWS_LOGGING_BITFIELD_CLEAR)
|
||||
#define _LWS_LBC (LWS_LOGGING_BITFIELD_CLEAR)
|
||||
#else
|
||||
#define _LWS_LBC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compute the final active logging bitfield for build
|
||||
*/
|
||||
#define _LWS_ENABLED_LOGS (((_LWS_LINIT) | (_LWS_LBS)) & ~(_LWS_LBC))
|
||||
|
||||
/*
|
||||
* Individually enable or disable log levels for build
|
||||
* depending on what was computed
|
||||
*/
|
||||
|
||||
/*
|
||||
* Process scope logs
|
||||
*/
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_err(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_warn(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_NOTICE)
|
||||
#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_notice(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_INFO)
|
||||
#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_info(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
||||
#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_debug(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_PARSER)
|
||||
#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_parser(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_HEADER)
|
||||
#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_header(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_EXT)
|
||||
#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ext(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_CLIENT)
|
||||
#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_client(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_LATENCY)
|
||||
#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_latency(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_THREAD)
|
||||
#define lwsl_thread(...) _lws_log(LLL_THREAD, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_thread(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_USER)
|
||||
#define lwsl_user(...) _lws_log(LLL_USER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_user(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define lwsl_hexdump_err(...) lwsl_hexdump_level(LLL_ERR, __VA_ARGS__)
|
||||
#define lwsl_hexdump_warn(...) lwsl_hexdump_level(LLL_WARN, __VA_ARGS__)
|
||||
#define lwsl_hexdump_notice(...) lwsl_hexdump_level(LLL_NOTICE, __VA_ARGS__)
|
||||
#define lwsl_hexdump_info(...) lwsl_hexdump_level(LLL_INFO, __VA_ARGS__)
|
||||
#define lwsl_hexdump_debug(...) lwsl_hexdump_level(LLL_DEBUG, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* lws_context scope logs
|
||||
*/
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
#define lwsl_cx_err(_c, ...) lwsl_cx(_c, LLL_ERR, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_err(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
#define lwsl_cx_warn(_c, ...) lwsl_cx(_c, LLL_WARN, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_warn(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_NOTICE)
|
||||
#define lwsl_cx_notice(_c, ...) lwsl_cx(_c, LLL_NOTICE, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_notice(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_INFO)
|
||||
#define lwsl_cx_info(_c, ...) lwsl_cx(_c, LLL_INFO, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_info(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
||||
#define lwsl_cx_debug(_c, ...) lwsl_cx(_c, LLL_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_debug(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_PARSER)
|
||||
#define lwsl_cx_parser(_c, ...) lwsl_cx(_c, LLL_PARSER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_parser(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_HEADER)
|
||||
#define lwsl_cx_header(_c, ...) lwsl_cx(_c, LLL_HEADER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_header(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_EXT)
|
||||
#define lwsl_cx_ext(_c, ...) lwsl_cx(_c, LLL_EXT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_ext(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_CLIENT)
|
||||
#define lwsl_cx_client(_c, ...) lwsl_cx(_c, LLL_CLIENT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_client(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_LATENCY)
|
||||
#define lwsl_cx_latency(_c, ...) lwsl_cx(_c, LLL_LATENCY, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_latency(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_THREAD)
|
||||
#define lwsl_cx_thread(_c, ...) lwsl_cx(_c, LLL_THREAD, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_thread(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_USER)
|
||||
#define lwsl_cx_user(_c, ...) lwsl_cx(_c, LLL_USER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_cx_user(_c, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define lwsl_hexdump_cx_err(_c, ...) lwsl_hexdump_context(_c, LLL_ERR, __VA_ARGS__)
|
||||
#define lwsl_hexdump_cx_warn(_c, ...) lwsl_hexdump_context(_c, LLL_WARN, __VA_ARGS__)
|
||||
#define lwsl_hexdump_cx_notice(_c, ...) lwsl_hexdump_context(_c, LLL_NOTICE, __VA_ARGS__)
|
||||
#define lwsl_hexdump_cx_info(_c, ...) lwsl_hexdump_context(_c, LLL_INFO, __VA_ARGS__)
|
||||
#define lwsl_hexdump_cx_debug(_c, ...) lwsl_hexdump_context(_c, LLL_DEBUG, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* lws_vhost
|
||||
*/
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
#define lwsl_vhost_err(_v, ...) lwsl_vhost(_v, LLL_ERR, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_err(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
#define lwsl_vhost_warn(_v, ...) lwsl_vhost(_v, LLL_WARN, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_warn(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_NOTICE)
|
||||
#define lwsl_vhost_notice(_v, ...) lwsl_vhost(_v, LLL_NOTICE, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_notice(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_INFO)
|
||||
#define lwsl_vhost_info(_v, ...) lwsl_vhost(_v, LLL_INFO, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_info(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
||||
#define lwsl_vhost_debug(_v, ...) lwsl_vhost(_v, LLL_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_debug(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_PARSER)
|
||||
#define lwsl_vhost_parser(_v, ...) lwsl_vhost(_v, LLL_PARSER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_parser(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_HEADER)
|
||||
#define lwsl_vhost_header(_v, ...) lwsl_vhost(_v, LLL_HEADER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_header(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_EXT)
|
||||
#define lwsl_vhost_ext(_v, ...) lwsl_vhost(_v, LLL_EXT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_ext(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_CLIENT)
|
||||
#define lwsl_vhost_client(_v, ...) lwsl_vhost(_v, LLL_CLIENT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_client(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_LATENCY)
|
||||
#define lwsl_vhost_latency(_v, ...) lwsl_vhost(_v, LLL_LATENCY, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_latency(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_THREAD)
|
||||
#define lwsl_vhost_thread(_v, ...) lwsl_vhost(_v, LLL_THREAD, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_thread(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_USER)
|
||||
#define lwsl_vhost_user(_v, ...) lwsl_vhost(_v, LLL_USER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_vhost_user(_v, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define lwsl_hexdump_vhost_err(_v, ...) lwsl_hexdump_vhost(_v, LLL_ERR, __VA_ARGS__)
|
||||
#define lwsl_hexdump_vhost_warn(_v, ...) lwsl_hexdump_vhost(_v, LLL_WARN, __VA_ARGS__)
|
||||
#define lwsl_hexdump_vhost_notice(_v, ...) lwsl_hexdump_vhost(_v, LLL_NOTICE, __VA_ARGS__)
|
||||
#define lwsl_hexdump_vhost_info(_v, ...) lwsl_hexdump_vhost(_v, LLL_INFO, __VA_ARGS__)
|
||||
#define lwsl_hexdump_vhost_debug(_v, ...) lwsl_hexdump_vhost(_v, LLL_DEBUG, __VA_ARGS__)
|
||||
|
||||
|
||||
/*
|
||||
* lws_wsi
|
||||
*/
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
#define lwsl_wsi_err(_w, ...) lwsl_wsi(_w, LLL_ERR, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_err(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
#define lwsl_wsi_warn(_w, ...) lwsl_wsi(_w, LLL_WARN, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_warn(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_NOTICE)
|
||||
#define lwsl_wsi_notice(_w, ...) lwsl_wsi(_w, LLL_NOTICE, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_notice(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_INFO)
|
||||
#define lwsl_wsi_info(_w, ...) lwsl_wsi(_w, LLL_INFO, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_info(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
||||
#define lwsl_wsi_debug(_w, ...) lwsl_wsi(_w, LLL_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_debug(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_PARSER)
|
||||
#define lwsl_wsi_parser(_w, ...) lwsl_wsi(_w, LLL_PARSER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_parser(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_HEADER)
|
||||
#define lwsl_wsi_header(_w, ...) lwsl_wsi(_w, LLL_HEADER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_header(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_EXT)
|
||||
#define lwsl_wsi_ext(_w, ...) lwsl_wsi(_w, LLL_EXT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_ext(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_CLIENT)
|
||||
#define lwsl_wsi_client(_w, ...) lwsl_wsi(_w, LLL_CLIENT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_client(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_LATENCY)
|
||||
#define lwsl_wsi_latency(_w, ...) lwsl_wsi(_w, LLL_LATENCY, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_latency(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_THREAD)
|
||||
#define lwsl_wsi_thread(_w, ...) lwsl_wsi(_w, LLL_THREAD, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_thread(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_USER)
|
||||
#define lwsl_wsi_user(_w, ...) lwsl_wsi(_w, LLL_USER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_wsi_user(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define lwsl_hexdump_wsi_err(_v, ...) lwsl_hexdump_wsi(_v, LLL_ERR, __VA_ARGS__)
|
||||
#define lwsl_hexdump_wsi_warn(_v, ...) lwsl_hexdump_wsi(_v, LLL_WARN, __VA_ARGS__)
|
||||
#define lwsl_hexdump_wsi_notice(_v, ...) lwsl_hexdump_wsi(_v, LLL_NOTICE, __VA_ARGS__)
|
||||
#define lwsl_hexdump_wsi_info(_v, ...) lwsl_hexdump_wsi(_v, LLL_INFO, __VA_ARGS__)
|
||||
#define lwsl_hexdump_wsi_debug(_v, ...) lwsl_hexdump_wsi(_v, LLL_DEBUG, __VA_ARGS__)
|
||||
|
||||
|
||||
/*
|
||||
* lwsl_ss
|
||||
*/
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_ERR)
|
||||
#define lwsl_ss_err(_w, ...) lwsl_ss(_w, LLL_ERR, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_err(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_WARN)
|
||||
#define lwsl_ss_warn(_w, ...) lwsl_ss(_w, LLL_WARN, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_warn(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_NOTICE)
|
||||
#define lwsl_ss_notice(_w, ...) lwsl_ss(_w, LLL_NOTICE, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_notice(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_INFO)
|
||||
#define lwsl_ss_info(_w, ...) lwsl_ss(_w, LLL_INFO, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_info(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_DEBUG)
|
||||
#define lwsl_ss_debug(_w, ...) lwsl_ss(_w, LLL_DEBUG, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_debug(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_PARSER)
|
||||
#define lwsl_ss_parser(_w, ...) lwsl_ss(_w, LLL_PARSER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_parser(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_HEADER)
|
||||
#define lwsl_ss_header(_w, ...) lwsl_ss(_w, LLL_HEADER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_header(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_EXT)
|
||||
#define lwsl_ss_ext(_w, ...) lwsl_ss(_w, LLL_EXT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_ext(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_CLIENT)
|
||||
#define lwsl_ss_client(_w, ...) lwsl_ss(_w, LLL_CLIENT, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_client(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_LATENCY)
|
||||
#define lwsl_ss_latency(_w, ...) lwsl_ss(_w, LLL_LATENCY, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_latency(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_THREAD)
|
||||
#define lwsl_ss_thread(_w, ...) lwsl_ss(_w, LLL_THREAD, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_thread(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#if (_LWS_ENABLED_LOGS & LLL_USER)
|
||||
#define lwsl_ss_user(_w, ...) lwsl_ss(_w, LLL_USER, __VA_ARGS__)
|
||||
#else
|
||||
#define lwsl_ss_user(_w, ...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define lwsl_hexdump_ss_err(_v, ...) lwsl_hexdump_ss(_v, LLL_ERR, __VA_ARGS__)
|
||||
#define lwsl_hexdump_ss_warn(_v, ...) lwsl_hexdump_ss(_v, LLL_WARN, __VA_ARGS__)
|
||||
#define lwsl_hexdump_ss_notice(_v, ...) lwsl_hexdump_ss(_v, LLL_NOTICE, __VA_ARGS__)
|
||||
#define lwsl_hexdump_ss_info(_v, ...) lwsl_hexdump_ss(_v, LLL_INFO, __VA_ARGS__)
|
||||
#define lwsl_hexdump_ss_debug(_v, ...) lwsl_hexdump_ss(_v, LLL_DEBUG, __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* lwsl_hexdump_level() - helper to hexdump a buffer at a selected debug level
|
||||
*
|
||||
* \param level: one of LLL_ constants
|
||||
* \param vbuf: buffer start to dump
|
||||
* \param len: length of buffer to dump
|
||||
*
|
||||
* If \p level is visible, does a nice hexdump -C style dump of \p vbuf for
|
||||
* \p len bytes. This can be extremely convenient while debugging.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_hexdump_level(int level, const void *vbuf, size_t len);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_hexdump_level_cx(lws_log_cx_t *cx, lws_log_prepend_cx_t prep, void *obj,
|
||||
int hexdump_level, const void *vbuf, size_t len);
|
||||
|
||||
/**
|
||||
* lwsl_hexdump() - helper to hexdump a buffer (DEBUG builds only)
|
||||
*
|
||||
* \param buf: buffer start to dump
|
||||
* \param len: length of buffer to dump
|
||||
*
|
||||
* Calls through to lwsl_hexdump_level(LLL_DEBUG, ... for compatability.
|
||||
* It's better to use lwsl_hexdump_level(level, ... directly so you can control
|
||||
* the visibility.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_hexdump(const void *buf, size_t len);
|
||||
|
||||
/**
|
||||
* lws_is_be() - returns nonzero if the platform is Big Endian
|
||||
*/
|
||||
static LWS_INLINE int lws_is_be(void) {
|
||||
const int probe = ~0xff;
|
||||
|
||||
return *(const char *)&probe;
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_set_log_level() - Set the logging bitfield
|
||||
* \param level: OR together the LLL_ debug contexts you want output from
|
||||
* \param log_emit_function: NULL to leave it as it is, or a user-supplied
|
||||
* function to perform log string emission instead of
|
||||
* the default stderr one.
|
||||
*
|
||||
* log level defaults to "err", "warn" and "notice" contexts enabled and
|
||||
* emission on stderr. If stderr is a tty (according to isatty()) then
|
||||
* the output is coloured according to the log level using ANSI escapes.
|
||||
*
|
||||
* You can set the default security level for logging using the
|
||||
* secrecy_and_log_level() macro to set the \p level parameter, eg
|
||||
*
|
||||
* lws_set_log_level(secrecy_and_log_level(LWS_SECRECY_PII, LLL_ERR | LLL_WARN),
|
||||
* my_emit_function);
|
||||
*
|
||||
* Normally you can just leave it at the default.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_set_log_level(int level, lws_log_emit_t log_emit_function);
|
||||
|
||||
/**
|
||||
* lwsl_emit_syslog() - helper log emit function writes to system log
|
||||
*
|
||||
* \param level: one of LLL_ log level indexes
|
||||
* \param line: log string
|
||||
*
|
||||
* You use this by passing the function pointer to lws_set_log_level(), to set
|
||||
* it as the log emit function, it is not called directly.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_emit_syslog(int level, const char *line);
|
||||
|
||||
/**
|
||||
* lwsl_emit_stderr() - helper log emit function writes to stderr
|
||||
*
|
||||
* \param level: one of LLL_ log level indexes
|
||||
* \param line: log string
|
||||
*
|
||||
* You use this by passing the function pointer to lws_set_log_level(), to set
|
||||
* it as the log emit function, it is not called directly.
|
||||
*
|
||||
* It prepends a system timestamp like [2018/11/13 07:41:57:3989]
|
||||
*
|
||||
* If stderr is a tty, then ansi colour codes are added.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_emit_stderr(int level, const char *line);
|
||||
|
||||
/**
|
||||
* lwsl_emit_stderr_notimestamp() - helper log emit function writes to stderr
|
||||
*
|
||||
* \param level: one of LLL_ log level indexes
|
||||
* \param line: log string
|
||||
*
|
||||
* You use this by passing the function pointer to lws_set_log_level(), to set
|
||||
* it as the log emit function, it is not called directly.
|
||||
*
|
||||
* If stderr is a tty, then ansi colour codes are added.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_emit_stderr_notimestamp(int level, const char *line);
|
||||
|
||||
/**
|
||||
* lwsl_visible() - returns true if the log level should be printed
|
||||
*
|
||||
* \param level: one of LLL_ log level indexes
|
||||
*
|
||||
* This is useful if you have to do work to generate the log content, you
|
||||
* can skip the work if the log level used to print it is not actually
|
||||
* enabled at runtime.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lwsl_visible(int level);
|
||||
|
||||
struct lws;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const char *
|
||||
lws_wsi_tag(struct lws *wsi);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsl_refcount_cx(lws_log_cx_t *cx, int _new);
|
||||
|
||||
///@}
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup lwsac lwsac
|
||||
*
|
||||
* ##Allocated Chunks
|
||||
*
|
||||
* If you know you will be allocating a large, unknown number of same or
|
||||
* differently sized objects, it's certainly possible to do it with libc
|
||||
* malloc. However the allocation cost in time and memory overhead can
|
||||
* add up, and deallocation means walking the structure of every object and
|
||||
* freeing them in turn.
|
||||
*
|
||||
* lwsac (LWS Allocated Chunks) allocates chunks intended to be larger
|
||||
* than your objects (4000 bytes by default) which you linearly allocate from
|
||||
* using lwsac_use().
|
||||
*
|
||||
* If your next request won't fit in the current chunk, a new chunk is added
|
||||
* to the chain of chunks and the allocaton done from there. If the request
|
||||
* is larger than the chunk size, an oversize chunk is created to satisfy it.
|
||||
*
|
||||
* When you are finished with the allocations, you call lwsac_free() and
|
||||
* free all the *chunks*. So you may have thousands of objects in the chunks,
|
||||
* but they are all destroyed with the chunks without having to deallocate them
|
||||
* one by one pointlessly.
|
||||
*/
|
||||
///@{
|
||||
|
||||
struct lwsac;
|
||||
typedef unsigned char * lwsac_cached_file_t;
|
||||
|
||||
|
||||
#define lws_list_ptr_container(P,T,M) ((T *)((char *)(P) - offsetof(T, M)))
|
||||
|
||||
/*
|
||||
* linked-list helper that's commonly useful to manage lists of things
|
||||
* allocated using lwsac.
|
||||
*
|
||||
* These lists point to their corresponding "next" member in the target, NOT
|
||||
* the original containing struct. To get the containing struct, you must use
|
||||
* lws_list_ptr_container() to convert.
|
||||
*
|
||||
* It's like that because it means we no longer have to have the next pointer
|
||||
* at the start of the struct, and we can have the same struct on multiple
|
||||
* linked-lists with everything held in the struct itself.
|
||||
*/
|
||||
typedef void * lws_list_ptr;
|
||||
|
||||
/*
|
||||
* optional sorting callback called by lws_list_ptr_insert() to sort the right
|
||||
* things inside the opqaue struct being sorted / inserted on the list.
|
||||
*/
|
||||
typedef int (*lws_list_ptr_sort_func_t)(lws_list_ptr a, lws_list_ptr b);
|
||||
|
||||
#define lws_list_ptr_advance(_lp) _lp = *((void **)_lp)
|
||||
|
||||
/* sort may be NULL if you don't care about order */
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_list_ptr_insert(lws_list_ptr *phead, lws_list_ptr *add,
|
||||
lws_list_ptr_sort_func_t sort);
|
||||
|
||||
|
||||
/**
|
||||
* lwsac_use - allocate / use some memory from a lwsac
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
* \param ensure: the number of bytes we want to use
|
||||
* \param chunk_size: 0, or the size of the chunk to (over)allocate if
|
||||
* what we want won't fit in the current tail chunk. If
|
||||
* 0, the default value of 4000 is used. If ensure is
|
||||
* larger, it is used instead.
|
||||
*
|
||||
* This also serves to init the lwsac if *head is NULL. Basically it does
|
||||
* whatever is necessary to return you a pointer to ensure bytes of memory
|
||||
* reserved for the caller.
|
||||
*
|
||||
* This always allocates in the current chunk or a new chunk... see the
|
||||
* lwsac_use_backfill() variant to try first to find space in earlier chunks.
|
||||
*
|
||||
* Returns NULL if OOM.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size);
|
||||
|
||||
/**
|
||||
* lwsac_use_backfill - allocate / use some memory from a lwsac
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
* \param ensure: the number of bytes we want to use
|
||||
* \param chunk_size: 0, or the size of the chunk to (over)allocate if
|
||||
* what we want won't fit in the current tail chunk. If
|
||||
* 0, the default value of 4000 is used. If ensure is
|
||||
* larger, it is used instead.
|
||||
*
|
||||
* This also serves to init the lwsac if *head is NULL. Basically it does
|
||||
* whatever is necessary to return you a pointer to ensure bytes of memory
|
||||
* reserved for the caller.
|
||||
*
|
||||
* Also checks if earlier blocks have enough remaining space to take the
|
||||
* allocation before making a new allocation.
|
||||
*
|
||||
* Returns NULL if OOM.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lwsac_use_backfill(struct lwsac **head, size_t ensure, size_t chunk_size);
|
||||
|
||||
/**
|
||||
* lwsac_use - allocate / use some memory from a lwsac
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
* \param ensure: the number of bytes we want to use, which must be zeroed
|
||||
* \param chunk_size: 0, or the size of the chunk to (over)allocate if
|
||||
* what we want won't fit in the current tail chunk. If
|
||||
* 0, the default value of 4000 is used. If ensure is
|
||||
* larger, it is used instead.
|
||||
*
|
||||
* Same as lwsac_use(), but \p ensure bytes of memory at the return address
|
||||
* are zero'd before returning.
|
||||
*
|
||||
* Returns NULL if OOM.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lwsac_use_zero(struct lwsac **head, size_t ensure, size_t chunk_size);
|
||||
|
||||
#define lwsac_use_zeroed lwsac_use_zero
|
||||
|
||||
/**
|
||||
* lwsac_free - deallocate all chunks in the lwsac and set head NULL
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
*
|
||||
* This deallocates all chunks in the lwsac, then sets *head to NULL. All
|
||||
* lwsac_use() pointers are invalidated in one hit without individual frees.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_free(struct lwsac **head);
|
||||
|
||||
/*
|
||||
* Optional helpers useful for where consumers may need to defer destruction
|
||||
* until all consumers are finished with the lwsac
|
||||
*/
|
||||
|
||||
/**
|
||||
* lwsac_detach() - destroy an lwsac unless somebody else is referencing it
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
*
|
||||
* The creator of the lwsac can all this instead of lwsac_free() when it itself
|
||||
* has finished with the lwsac, but other code may be consuming it.
|
||||
*
|
||||
* If there are no other references, the lwsac is destroyed, *head is set to
|
||||
* NULL and that's the end; however if something else has called
|
||||
* lwsac_reference() on the lwsac, it simply returns. When lws_unreference()
|
||||
* is called and no references are left, it will be destroyed then.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_detach(struct lwsac **head);
|
||||
|
||||
/**
|
||||
* lwsac_reference() - increase the lwsac reference count
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
*
|
||||
* Increment the reference count on the lwsac to defer destruction.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_reference(struct lwsac *head);
|
||||
|
||||
/**
|
||||
* lwsac_unreference() - decrease the lwsac reference count
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
*
|
||||
* Decrement the reference count on the lwsac... if it reached 0 on a detached
|
||||
* lwsac then the lwsac is immediately destroyed and *head set to NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_unreference(struct lwsac **head);
|
||||
|
||||
/**
|
||||
* lwsac_extend() - try to increase the size of the last block
|
||||
*
|
||||
* \param head: pointer to the lwsac list object
|
||||
* \param amount: amount to try to increase usage for
|
||||
*
|
||||
* This will either increase the usage reservation of the last allocated block
|
||||
* by amount and return 0, or fail and return 1.
|
||||
*
|
||||
* This is very cheap to call and is designed to optimize usage after a static
|
||||
* struct for vari-sized additional content which may flow into an additional
|
||||
* block in a new chunk if necessary, but wants to make the most of the space
|
||||
* in front of it first to try to avoid gaps and the new chunk if it can.
|
||||
*
|
||||
* The additional area if the call succeeds will have been memset to 0.
|
||||
*
|
||||
* To use it, the following must be true:
|
||||
*
|
||||
* - only the last lwsac use can be extended
|
||||
*
|
||||
* - if another use happens inbetween the use and extend, it will break
|
||||
*
|
||||
* - the use cannot have been using backfill
|
||||
*
|
||||
* - a user object must be tracking the current allocated size of the last use
|
||||
* (lwsac doesn't know it) and increment by amount if the extend call succeeds
|
||||
*
|
||||
* Despite these restrictions this can be an important optimization for some
|
||||
* cases
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lwsac_extend(struct lwsac *head, size_t amount);
|
||||
|
||||
/* helpers to keep a file cached in memory */
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_use_cached_file_start(lwsac_cached_file_t cache);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_use_cached_file_end(lwsac_cached_file_t *cache);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_use_cached_file_detach(lwsac_cached_file_t *cache);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lwsac_cached_file(const char *filepath, lwsac_cached_file_t *cache,
|
||||
size_t *len);
|
||||
|
||||
/* more advanced helpers */
|
||||
|
||||
/* offset from lac to start of payload, first = 1 = first lac in chain */
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lwsac_sizeof(int first);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lwsac_get_tail_pos(struct lwsac *lac);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN struct lwsac *
|
||||
lwsac_get_next(struct lwsac *lac);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lwsac_align(size_t length);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lwsac_info(struct lwsac *head);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN uint64_t
|
||||
lwsac_total_alloc(struct lwsac *head);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN uint64_t
|
||||
lwsac_total_overhead(struct lwsac *head);
|
||||
|
||||
/**
|
||||
* lwsac_scan_extant() - returns existing copy of blob, or NULL
|
||||
*
|
||||
* \param head: the lwsac to scan
|
||||
* \param find: the blob to look for
|
||||
* \param len: the length of the blob to look for
|
||||
* \param nul: nonzero if the next byte must be NUL
|
||||
*
|
||||
* Helper that looks through a whole lwsac for a given binary blob already
|
||||
* present. Used in the case that lwsac contents are const once written, and
|
||||
* strings or blobs may be repeated in the input: this allows the earlier
|
||||
* copy to be pointed to by subsequent references without repeating the string
|
||||
* or blob redundantly.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN uint8_t *
|
||||
lwsac_scan_extant(struct lwsac *head, uint8_t *find, size_t len, int nul);
|
||||
|
||||
///@}
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** \defgroup lws_map generic map apis
|
||||
* ##Generic map structures and apis
|
||||
* \ingroup lwsapi
|
||||
*
|
||||
* lws_map
|
||||
*
|
||||
* Discrete owner object represents the whole map, created with key-specific
|
||||
* ops for hashing the key to a uint32_t and comparing two keys. Owns a list
|
||||
* of hash tables whose size / modulo it set at creation time.
|
||||
*
|
||||
* Items in the map are contained in a lws_map_item_t that is indexed in a
|
||||
* hash table.
|
||||
*
|
||||
* It's difficult to make a single compact map abstraction that fits all cases,
|
||||
* this is useful to the extent you have the memory to trade off the number of
|
||||
* hashtables needed for the amount of items and the lookup latency limit for
|
||||
* your application, typically for hundreds or low thousands of items.
|
||||
*/
|
||||
//@{
|
||||
|
||||
typedef struct lws_map lws_map_t;
|
||||
typedef struct lws_map_item lws_map_item_t;
|
||||
|
||||
typedef void * lws_map_key_t;
|
||||
typedef void * lws_map_value_t;
|
||||
typedef uint32_t lws_map_hash_t;
|
||||
|
||||
typedef lws_map_hash_t (*lws_map_hash_from_key_t)(const lws_map_key_t key,
|
||||
size_t kl);
|
||||
typedef int (*lws_map_compare_key_t)(const lws_map_key_t key1, size_t kl1,
|
||||
const lws_map_value_t key2, size_t kl2);
|
||||
typedef void * (*lws_map_alloc_t)(struct lws_map *mo, size_t x);
|
||||
typedef void (*lws_map_free_t)(void *);
|
||||
|
||||
/*
|
||||
* Creation parameters for the map, copied into the map owner
|
||||
*/
|
||||
|
||||
typedef struct lws_map_info {
|
||||
lws_map_hash_from_key_t _hash;
|
||||
lws_map_compare_key_t _compare;
|
||||
lws_map_alloc_t _alloc; /* NULL = lws_malloc */
|
||||
lws_map_free_t _free; /* NULL = lws_free */
|
||||
|
||||
void *opaque;
|
||||
/**< &lwsac if using lwsac allocator */
|
||||
void *aux;
|
||||
/**< chunk size if using lwsac allocator */
|
||||
/**< this can be used by the alloc handler, eg for lws_ac */
|
||||
size_t modulo;
|
||||
/**< number of hashed owner lists to create */
|
||||
} lws_map_info_t;
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN const void *
|
||||
lws_map_item_key(lws_map_item_t *_item);
|
||||
LWS_VISIBLE LWS_EXTERN const void *
|
||||
lws_map_item_value(lws_map_item_t *_item);
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lws_map_item_key_len(lws_map_item_t *_item);
|
||||
LWS_VISIBLE LWS_EXTERN size_t
|
||||
lws_map_item_value_len(lws_map_item_t *_item);
|
||||
|
||||
/*
|
||||
* Helpers for C string keys case
|
||||
*/
|
||||
|
||||
#define lws_map_item_create_ks(_map, _str, _v, _vl) \
|
||||
lws_map_item_create(_map, (const lws_map_key_t)_str, \
|
||||
strlen(_str), (const lws_map_value_t)_v, \
|
||||
_vl)
|
||||
#define lws_map_item_lookup_ks(_map, _str) \
|
||||
lws_map_item_lookup(_map, (const lws_map_key_t)_str, strlen(_str))
|
||||
|
||||
/**
|
||||
* lws_map_create() - create a map object and hashtables on heap
|
||||
*
|
||||
* \param info: description of map to create
|
||||
*
|
||||
* Creates a map object on heap, using lws_malloc().
|
||||
*
|
||||
* \p info may be all zeros inside, if so, modulo defaults to 8, and the
|
||||
* operation callbacks default to using lws_malloc() / _free() for item alloc,
|
||||
* a default xor / shift based hash and simple linear memory key compare.
|
||||
*
|
||||
* For less typical use-cases, the provided \p info members can be tuned to
|
||||
* control how the allocation of mapped items is done, lws provides two exports
|
||||
* lws_map_alloc_lwsac() and lws_map_free_lwsac() that can be used for _alloc
|
||||
* and _free to have items allocated inside an lwsac.
|
||||
*
|
||||
* The map itself is created on the heap directly, the info._alloc() op is only
|
||||
* used when creating items.
|
||||
*
|
||||
* keys have individual memory sizes and do not need to all be the same length.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN lws_map_t *
|
||||
lws_map_create(const lws_map_info_t *info);
|
||||
|
||||
/*
|
||||
* helpers that can be used for info._alloc and info._free if using lwsac
|
||||
* allocation for items, set info.opaque to point to the lwsac pointer, and
|
||||
* aux to (void *)chunksize, or leave zero / NULL for the default
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void *
|
||||
lws_map_alloc_lwsac(struct lws_map *map, size_t x);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_map_free_lwsac(void *v);
|
||||
|
||||
/**
|
||||
* lws_map_destroy() - deallocate all items and free map
|
||||
*
|
||||
* \param pmap: pointer to pointer map object to deallocate
|
||||
*
|
||||
* Frees all items in the map, using info._free(), and then frees the map
|
||||
* from heap directly. \p *pmap is set to NULL.
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_map_destroy(lws_map_t **pmap);
|
||||
|
||||
/**
|
||||
* lws_map_item_create() - allocate and map an item into an existing map
|
||||
*
|
||||
* \param map: the map to add items into
|
||||
* \param key: the key, may be any kind of object
|
||||
* \param keylen: the length of the key in bytes
|
||||
* \param value: the value, may be any kind of object
|
||||
* \param valuelen: the length of value
|
||||
*
|
||||
* Allocates space for the item, key and value using the map allocator, and
|
||||
* if non-NULL, copies the key and value into the item.
|
||||
*
|
||||
* If an item with the same key exists, it is removed and destroyed before
|
||||
* creating and adding the new one.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN lws_map_item_t *
|
||||
lws_map_item_create(lws_map_t *map,
|
||||
const lws_map_key_t key, size_t keylen,
|
||||
const lws_map_value_t value, size_t valuelen);
|
||||
|
||||
/**
|
||||
* lws_map_item_destroy() - remove item from map and free
|
||||
*
|
||||
* \param item: the item in the map to remove and free
|
||||
*/
|
||||
LWS_VISIBLE LWS_EXTERN void
|
||||
lws_map_item_destroy(lws_map_item_t *item);
|
||||
|
||||
/**
|
||||
* lws_map_item_lookup() - look for a item with the given key in the map
|
||||
*
|
||||
* \param map: the map
|
||||
* \param key: the key to look for
|
||||
* \param keylen: the length of the key to look for
|
||||
*
|
||||
* Searches for the key in the map, using the map's key hash and key compare
|
||||
* functions.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN lws_map_item_t *
|
||||
lws_map_item_lookup(lws_map_t *map, const lws_map_key_t key, size_t keylen);
|
||||
|
||||
//@}
|
||||
|
|
@ -1,329 +0,0 @@
|
|||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Public apis related to metric collection and reporting
|
||||
*/
|
||||
|
||||
/* lws_metrics public part */
|
||||
|
||||
typedef uint64_t u_mt_t;
|
||||
|
||||
enum {
|
||||
LWSMTFL_REPORT_OUTLIERS = (1 << 0),
|
||||
/**< track outliers and report them internally */
|
||||
LWSMTFL_REPORT_OOB = (1 << 1),
|
||||
/**< report events as they happen */
|
||||
LWSMTFL_REPORT_INACTIVITY_AT_PERIODIC = (1 << 2),
|
||||
/**< explicitly externally report no activity at periodic cb, by
|
||||
* default no events in the period is just not reported */
|
||||
LWSMTFL_REPORT_MEAN = (1 << 3),
|
||||
/**< average/min/max is meaningful, else only sum is meaningful */
|
||||
LWSMTFL_REPORT_ONLY_GO = (1 << 4),
|
||||
/**< no-go pieces invalid */
|
||||
LWSMTFL_REPORT_DUTY_WALLCLOCK_US = (1 << 5),
|
||||
/**< aggregate compares to wallclock us for duty cycle */
|
||||
LWSMTFL_REPORT_HIST = (1 << 6),
|
||||
/**< our type is histogram (otherwise, sum / mean aggregation) */
|
||||
};
|
||||
|
||||
/*
|
||||
* lws_metrics_tag allows your object to accumulate OpenMetrics-style
|
||||
* descriptive tags before accounting for it with a metrics object at the end.
|
||||
*
|
||||
* Tags should represent low entropy information that is likely to repeat
|
||||
* identically, so, eg, http method name, not eg, latency in us which is
|
||||
* unlikely to be seen the same twice.
|
||||
*
|
||||
* Tags are just a list of name=value pairs, used for qualifying the final
|
||||
* metrics entry with decorations in additional dimensions. For example,
|
||||
* rather than keep individual metrics on methods, scheme, mountpoint, result
|
||||
* code, you can keep metrics on http transactions only, and qualify the
|
||||
* transaction metrics entries with tags that can be queried on the metrics
|
||||
* backend to get the finer-grained information.
|
||||
*
|
||||
* http_srv{code="404",mount="/",method="GET",scheme="http"} 3
|
||||
*
|
||||
* For OpenMetrics the tags are converted to a { list } and appended to the base
|
||||
* metrics name before using with actual metrics objects, the same set of tags
|
||||
* on different transactions resolve to the same qualification string.
|
||||
*/
|
||||
|
||||
typedef struct lws_metrics_tag {
|
||||
lws_dll2_t list;
|
||||
|
||||
const char *name; /* tag, intended to be in .rodata, not copied */
|
||||
/* overallocated value */
|
||||
} lws_metrics_tag_t;
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
lws_metrics_tag_add(lws_dll2_owner_t *owner, const char *name, const char *val);
|
||||
|
||||
#if defined(LWS_WITH_SYS_METRICS)
|
||||
/*
|
||||
* wsi-specific version that also appends the tag value to the lifecycle tag
|
||||
* used for logging the wsi identity
|
||||
*/
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
lws_metrics_tag_wsi_add(struct lws *wsi, const char *name, const char *val);
|
||||
#else
|
||||
#define lws_metrics_tag_wsi_add(_a, _b, _c)
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_SECURE_STREAMS)
|
||||
/*
|
||||
* ss-specific version that also appends the tag value to the lifecycle tag
|
||||
* used for logging the ss identity
|
||||
*/
|
||||
#if defined(LWS_WITH_SYS_METRICS)
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
lws_metrics_tag_ss_add(struct lws_ss_handle *ss, const char *name, const char *val);
|
||||
#else
|
||||
#define lws_metrics_tag_ss_add(_a, _b, _c)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE void
|
||||
lws_metrics_tags_destroy(lws_dll2_owner_t *owner);
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE size_t
|
||||
lws_metrics_tags_serialize(lws_dll2_owner_t *owner, char *buf, size_t len);
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE const char *
|
||||
lws_metrics_tag_get(lws_dll2_owner_t *owner, const char *name);
|
||||
|
||||
/* histogram bucket */
|
||||
|
||||
typedef struct lws_metric_bucket {
|
||||
struct lws_metric_bucket *next;
|
||||
uint64_t count;
|
||||
|
||||
/* name + NUL is overallocated */
|
||||
} lws_metric_bucket_t;
|
||||
|
||||
/* get overallocated name of bucket from bucket pointer */
|
||||
#define lws_metric_bucket_name_len(_b) (*((uint8_t *)&(_b)[1]))
|
||||
#define lws_metric_bucket_name(_b) (((const char *)&(_b)[1]) + 1)
|
||||
|
||||
/*
|
||||
* These represent persistent local event measurements. They may aggregate
|
||||
* a large number of events inbetween external dumping of summaries of the
|
||||
* period covered, in two different ways
|
||||
*
|
||||
* 1) aggregation by sum or mean, to absorb multiple scalar readings
|
||||
*
|
||||
* - go / no-go ratio counting
|
||||
* - mean averaging for, eg, latencies
|
||||
* - min / max for averaged values
|
||||
* - period the stats covers
|
||||
*
|
||||
* 2) aggregation by histogram, to absorb a range of outcomes that may occur
|
||||
* multiple times
|
||||
*
|
||||
* - add named buckets to histogram
|
||||
* - bucket has a 64-bit count
|
||||
* - bumping a bucket just increments the count if already exists, else adds
|
||||
* a new one with count set to 1
|
||||
*
|
||||
* The same type with a union covers both cases.
|
||||
*
|
||||
* The lws_system ops api that hooks lws_metrics up to a metrics backend is
|
||||
* given a pointer to these according to the related policy, eg, hourly, or
|
||||
* every event passed straight through.
|
||||
*/
|
||||
|
||||
typedef struct lws_metric_pub {
|
||||
const char *name;
|
||||
/**< eg, "n.cn.dns", "vh.myendpoint" */
|
||||
void *backend_opaque;
|
||||
/**< ignored by lws, backend handler completely owns it */
|
||||
|
||||
lws_usec_t us_first;
|
||||
/**< us time metric started collecting, reset to us_dumped at dump */
|
||||
lws_usec_t us_last;
|
||||
/**< 0, or us time last event, reset to 0 at last dump */
|
||||
lws_usec_t us_dumped;
|
||||
/**< 0 if never, else us time of last dump to external api */
|
||||
|
||||
/* scope of data in .u is "since last dump" --> */
|
||||
|
||||
union {
|
||||
/* aggregation, by sum or mean */
|
||||
|
||||
struct {
|
||||
u_mt_t sum[2];
|
||||
/**< go, no-go summed for mean or plan sum */
|
||||
u_mt_t min;
|
||||
/**< smallest individual measurement */
|
||||
u_mt_t max;
|
||||
/**< largest individual measurement */
|
||||
|
||||
uint32_t count[2];
|
||||
/**< go, no-go count of measurements in sum */
|
||||
} agg;
|
||||
|
||||
/* histogram with dynamic named buckets */
|
||||
|
||||
struct {
|
||||
lws_metric_bucket_t *head;
|
||||
/**< first bucket in our bucket list */
|
||||
|
||||
uint64_t total_count;
|
||||
/**< total count in all of our buckets */
|
||||
uint32_t list_size;
|
||||
/**< number of buckets in our bucket list */
|
||||
} hist;
|
||||
} u;
|
||||
|
||||
uint8_t flags;
|
||||
|
||||
} lws_metric_pub_t;
|
||||
|
||||
LWS_EXTERN LWS_VISIBLE void
|
||||
lws_metrics_hist_bump_priv_tagged(lws_metric_pub_t *mt, lws_dll2_owner_t *tow,
|
||||
lws_dll2_owner_t *tow2);
|
||||
|
||||
|
||||
/*
|
||||
* Calipers are a helper struct for implementing "hanging latency" detection,
|
||||
* where setting the start time and finding the end time may happen in more than
|
||||
* one place.
|
||||
*
|
||||
* There are convenience wrappers to eliminate caliper definitions and code
|
||||
* cleanly if WITH_SYS_METRICS is disabled for the build.
|
||||
*/
|
||||
|
||||
struct lws_metric;
|
||||
|
||||
typedef struct lws_metric_caliper {
|
||||
struct lws_dll2_owner mtags_owner; /**< collect tags here during
|
||||
* caliper lifetime */
|
||||
struct lws_metric *mt; /**< NULL == inactive */
|
||||
lws_usec_t us_start;
|
||||
} lws_metric_caliper_t;
|
||||
|
||||
#if defined(LWS_WITH_SYS_METRICS)
|
||||
#define lws_metrics_caliper_compose(_name) \
|
||||
lws_metric_caliper_t _name;
|
||||
#define lws_metrics_caliper_bind(_name, _mt) \
|
||||
{ if (_name.mt) { \
|
||||
lwsl_err("caliper: overwrite %s\n", \
|
||||
lws_metrics_priv_to_pub(_name.mt)->name); \
|
||||
assert(0); } \
|
||||
_name.mt = _mt; _name.us_start = lws_now_usecs(); }
|
||||
#define lws_metrics_caliper_declare(_name, _mt) \
|
||||
lws_metric_caliper_t _name = { .mt = _mt, .us_start = lws_now_usecs() }
|
||||
#define lws_metrics_caliper_report(_name, _go_nogo) \
|
||||
{ if (_name.us_start) { lws_metric_event(_name.mt, _go_nogo, \
|
||||
(u_mt_t)(lws_now_usecs() - \
|
||||
_name.us_start)); \
|
||||
} lws_metrics_caliper_done(_name); }
|
||||
#define lws_metrics_caliper_report_hist(_name, pwsi) if (_name.mt) { \
|
||||
lws_metrics_hist_bump_priv_tagged(lws_metrics_priv_to_pub(_name.mt), \
|
||||
&_name.mtags_owner, \
|
||||
pwsi ? &((pwsi)->cal_conn.mtags_owner) : NULL); \
|
||||
lws_metrics_caliper_done(_name); }
|
||||
|
||||
#define lws_metrics_caliper_cancel(_name) { lws_metrics_caliper_done(_name); }
|
||||
#define lws_metrics_hist_bump(_mt, _name) \
|
||||
lws_metrics_hist_bump_(_mt, _name)
|
||||
#define lws_metrics_hist_bump_priv(_mt, _name) \
|
||||
lws_metrics_hist_bump_(lws_metrics_priv_to_pub(_mt), _name)
|
||||
#define lws_metrics_caliper_done(_name) { \
|
||||
_name.us_start = 0; _name.mt = NULL; \
|
||||
lws_metrics_tags_destroy(&_name.mtags_owner); }
|
||||
#else
|
||||
#define lws_metrics_caliper_compose(_name)
|
||||
#define lws_metrics_caliper_bind(_name, _mt)
|
||||
#define lws_metrics_caliper_declare(_name, _mp)
|
||||
#define lws_metrics_caliper_report(_name, _go_nogo)
|
||||
#define lws_metrics_caliper_report_hist(_name, pwsiconn)
|
||||
#define lws_metrics_caliper_cancel(_name)
|
||||
#define lws_metrics_hist_bump(_mt, _name)
|
||||
#define lws_metrics_hist_bump_priv(_mt, _name)
|
||||
#define lws_metrics_caliper_done(_name)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lws_metrics_format() - helper to format a metrics object for logging
|
||||
*
|
||||
* \param pub: public part of metrics object
|
||||
* \param buf: output buffer to place string in
|
||||
* \param len: available length of \p buf
|
||||
*
|
||||
* Helper for describing the state of a metrics object as a human-readable
|
||||
* string, accounting for how its flags indicate what it contains. This is not
|
||||
* how you would report metrics, but during development it can be useful to
|
||||
* log them inbetween possibily long report intervals.
|
||||
*
|
||||
* It uses the metric's flags to adapt the format shown appropriately, eg,
|
||||
* as a histogram if LWSMTFL_REPORT_HIST etc
|
||||
*/
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
lws_metrics_format(lws_metric_pub_t *pub, lws_metric_bucket_t **sub,
|
||||
char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* lws_metrics_hist_bump() - add or increment histogram bucket
|
||||
*
|
||||
* \param pub: public part of metrics object
|
||||
* \param name: bucket name to increment
|
||||
*
|
||||
* Either increment the count of an existing bucket of the right name in the
|
||||
* metrics object, or add a new bucket of the given name and set its count to 1.
|
||||
*
|
||||
* The metrics object must have been created with flag LWSMTFL_REPORT_HIST
|
||||
*
|
||||
* Normally, you will actually use the preprocessor wrapper
|
||||
* lws_metrics_hist_bump() defined above, since this automatically takes care of
|
||||
* removing itself from the build if WITH_SYS_METRICS is not defined, without
|
||||
* needing any preprocessor conditionals.
|
||||
*/
|
||||
LWS_EXTERN LWS_VISIBLE int
|
||||
lws_metrics_hist_bump_(lws_metric_pub_t *pub, const char *name);
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_metrics_foreach(struct lws_context *ctx, void *user,
|
||||
int (*cb)(lws_metric_pub_t *pub, void *user));
|
||||
|
||||
LWS_VISIBLE LWS_EXTERN int
|
||||
lws_metrics_hist_bump_describe_wsi(struct lws *wsi, lws_metric_pub_t *pub,
|
||||
const char *name);
|
||||
|
||||
enum {
|
||||
LMT_NORMAL = 0, /* related to successful events */
|
||||
LMT_OUTLIER, /* related to successful events outside of bounds */
|
||||
|
||||
LMT_FAIL, /* related to failed events */
|
||||
|
||||
LMT_COUNT,
|
||||
};
|
||||
|
||||
typedef enum lws_metric_rpt {
|
||||
LMR_PERIODIC = 0, /* we are reporting on a schedule */
|
||||
LMR_OUTLIER, /* we are reporting the last outlier */
|
||||
} lws_metric_rpt_kind_t;
|
||||
|
||||
#define METRES_GO 0
|
||||
#define METRES_NOGO 1
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue