2018-11-30 22:52:05 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2015-01-16 02:40:39 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "WebGLValidateStrings.h"
|
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
#include <regex>
|
|
|
|
|
2020-02-28 12:16:29 +03:00
|
|
|
#include "WebGLTypes.h"
|
|
|
|
|
2015-01-16 02:40:39 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
/* GLSL ES 3.00 p17:
|
|
|
|
- Comments are delimited by / * and * /, or by // and a newline.
|
|
|
|
|
|
|
|
- '//' style comments include the initial '//' marker and continue up to, but
|
|
|
|
not including, the terminating newline.
|
|
|
|
|
|
|
|
- '/ * ... * /' comments include both the start and end marker.
|
|
|
|
|
|
|
|
- The begin comment delimiters (/ * or //) are not recognized as comment
|
|
|
|
delimiters inside of a comment, hence comments cannot be nested.
|
|
|
|
|
|
|
|
- Comments are treated syntactically as a single space.
|
|
|
|
*/
|
|
|
|
|
|
|
|
std::string CommentsToSpaces(const std::string& src) {
|
2020-02-28 12:16:29 +03:00
|
|
|
constexpr auto flags = std::regex::ECMAScript | std::regex::nosubs | std::regex::optimize;
|
2020-01-09 01:19:23 +03:00
|
|
|
|
2020-02-28 12:16:29 +03:00
|
|
|
static const auto RE_COMMENT_BEGIN = std::regex("/[*/]", flags);
|
|
|
|
static const auto RE_LINE_COMMENT_END = std::regex(R"([^\\]\n)", flags);
|
|
|
|
static const auto RE_BLOCK_COMMENT_END = std::regex(R"(\*/)", flags);
|
2020-02-26 04:27:01 +03:00
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
std::string ret;
|
|
|
|
ret.reserve(src.size());
|
|
|
|
|
2020-02-28 12:16:29 +03:00
|
|
|
// Replace all comments with block comments with the right number of newlines.
|
|
|
|
// Line positions may be off, but line numbers will be accurate, which is more important.
|
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
auto itr = src.begin();
|
2020-02-28 12:16:29 +03:00
|
|
|
const auto end = src.end();
|
2020-01-09 01:19:23 +03:00
|
|
|
std::smatch match;
|
2020-02-28 12:16:29 +03:00
|
|
|
while (std::regex_search(itr, end, match, RE_COMMENT_BEGIN)) {
|
|
|
|
MOZ_ASSERT(match.length() == 2);
|
|
|
|
const auto commentBegin = itr + match.position();
|
|
|
|
ret.append(itr, commentBegin);
|
|
|
|
|
|
|
|
itr = commentBegin + match.length();
|
|
|
|
|
|
|
|
const bool isBlockComment = (*(commentBegin + 1) == '*');
|
|
|
|
const auto* endRegex = &RE_LINE_COMMENT_END;
|
|
|
|
if (isBlockComment) {
|
|
|
|
endRegex = &RE_BLOCK_COMMENT_END;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isBlockComment) {
|
|
|
|
ret += "/*";
|
|
|
|
}
|
|
|
|
|
2020-03-09 06:19:25 +03:00
|
|
|
auto commentEnd = end;
|
|
|
|
if (!isBlockComment && itr != end && *itr == '\n') {
|
|
|
|
commentEnd = itr + 1; // '//\n'
|
|
|
|
} else if (std::regex_search(itr, end, match, *endRegex)) {
|
|
|
|
commentEnd = itr + match.position() + match.length();
|
|
|
|
} else {
|
|
|
|
return ret;
|
|
|
|
}
|
2020-02-28 12:16:29 +03:00
|
|
|
|
|
|
|
for (; itr != commentEnd; ++itr) {
|
|
|
|
const auto cur = *itr;
|
|
|
|
if (cur == '\n') {
|
|
|
|
ret += cur;
|
2020-01-09 01:19:23 +03:00
|
|
|
}
|
2020-02-28 12:16:29 +03:00
|
|
|
}
|
|
|
|
if (isBlockComment) {
|
|
|
|
ret += "*/";
|
2015-01-16 02:40:39 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-01-16 02:40:39 +03:00
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
ret.append(itr, end);
|
|
|
|
return ret;
|
2016-12-28 04:47:19 +03:00
|
|
|
}
|
2015-01-16 02:40:39 +03:00
|
|
|
|
2016-12-30 05:48:04 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2020-01-09 01:19:16 +03:00
|
|
|
static bool IsValidGLSLChar(const char c) {
|
2016-12-30 05:48:04 +03:00
|
|
|
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
|
|
|
|
('0' <= c && c <= '9')) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '\v':
|
|
|
|
case '\f':
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
case '_':
|
|
|
|
case '.':
|
|
|
|
case '+':
|
|
|
|
case '-':
|
|
|
|
case '/':
|
|
|
|
case '*':
|
|
|
|
case '%':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case '[':
|
|
|
|
case ']':
|
|
|
|
case '(':
|
|
|
|
case ')':
|
|
|
|
case '{':
|
|
|
|
case '}':
|
|
|
|
case '^':
|
|
|
|
case '|':
|
|
|
|
case '&':
|
|
|
|
case '~':
|
|
|
|
case '=':
|
|
|
|
case '!':
|
|
|
|
case ':':
|
|
|
|
case ';':
|
|
|
|
case ',':
|
|
|
|
case '?':
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////
|
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
Maybe<char> CheckGLSLPreprocString(const bool webgl2,
|
|
|
|
const std::string& string) {
|
|
|
|
for (const auto c : string) {
|
|
|
|
if (IsValidGLSLChar(c)) continue;
|
|
|
|
if (c == '#') continue;
|
|
|
|
if (c == '\\' && webgl2) continue;
|
2017-01-03 13:05:43 +03:00
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
return Some(c);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-01-09 01:19:23 +03:00
|
|
|
return {};
|
2015-01-16 02:40:39 +03:00
|
|
|
}
|
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
Maybe<webgl::ErrorInfo> CheckGLSLVariableName(const bool webgl2,
|
|
|
|
const std::string& name) {
|
|
|
|
if (name.empty()) return {};
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
const uint32_t maxSize = webgl2 ? 1024 : 256;
|
2020-01-09 01:19:16 +03:00
|
|
|
if (name.size() > maxSize) {
|
2020-01-09 01:19:23 +03:00
|
|
|
const auto info = nsPrintfCString(
|
|
|
|
"Identifier is %zu characters long, exceeds the"
|
2016-12-30 05:48:04 +03:00
|
|
|
" maximum allowed length of %u characters.",
|
2020-01-09 01:19:16 +03:00
|
|
|
name.size(), maxSize);
|
2020-01-09 01:19:23 +03:00
|
|
|
return Some(webgl::ErrorInfo{LOCAL_GL_INVALID_VALUE, info.BeginReading()});
|
2015-01-16 02:40:39 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-01-09 01:19:16 +03:00
|
|
|
for (const auto cur : name) {
|
2016-12-30 05:48:04 +03:00
|
|
|
if (!IsValidGLSLChar(cur)) {
|
2020-01-09 01:19:23 +03:00
|
|
|
const auto info =
|
|
|
|
nsPrintfCString("String contains the illegal character 0x%x'.", cur);
|
|
|
|
return Some(
|
|
|
|
webgl::ErrorInfo{LOCAL_GL_INVALID_VALUE, info.BeginReading()});
|
2016-12-30 05:48:04 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-01-16 02:40:39 +03:00
|
|
|
|
2020-01-09 01:19:16 +03:00
|
|
|
if (name.find("webgl_") == 0 || name.find("_webgl_") == 0) {
|
2020-01-09 01:19:23 +03:00
|
|
|
return Some(webgl::ErrorInfo{
|
|
|
|
LOCAL_GL_INVALID_OPERATION,
|
|
|
|
"String matches reserved GLSL prefix pattern /_?webgl_/."});
|
2015-01-16 02:40:39 +03:00
|
|
|
}
|
|
|
|
|
2020-01-09 01:19:23 +03:00
|
|
|
return {};
|
2015-01-16 02:40:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace mozilla
|