openssl use 1.1.1k , curl use static link

This commit is contained in:
yangchao 2022-01-06 18:17:41 +08:00
parent cfb451bd17
commit 5f4f7208b8
340 changed files with 34551 additions and 38557 deletions

View File

@ -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}
)

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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 */

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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 */

View File

@ -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);
};

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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
//@}

View File

@ -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>

View File

@ -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 */
};

View File

@ -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);

View File

@ -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
///@}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;
///@}

View File

@ -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
///@}

View File

@ -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
///@}

View File

@ -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);
///@}

View File

@ -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

View File

@ -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);
//@}

View File

@ -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

View File

@ -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);
///@}

View File

@ -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

View File

@ -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; \
} \
}
///@}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
///@}

View File

@ -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);
///@}

View File

@ -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);

View File

@ -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);

View File

@ -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);
///@}

View File

@ -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);
///@}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);
///@}

View File

@ -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
///@}

View File

@ -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);
//@}

View File

@ -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, \
}

View File

@ -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);
///@}

View File

@ -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);
///@}

View File

@ -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);
//@}

View File

@ -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