Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions cmake/Toolchain-wasm32-web.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

set(CMAKE_SYSTEM_PROCESSOR "wasm32" CACHE STRING "" FORCE)
set(CMAKE_SYSTEM_NAME "Emscripten" CACHE STRING "" FORCE)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_CROSSCOMPILING TRUE)
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
set(UNIX 1)
set(SYSTRIPLET "${CMAKE_SYSTEM_PROCESSOR}-unknown-emscripten" CACHE STRING "" FORCE)
add_compile_definitions(_LIBCPP_ENABLE_EXPERIMENTAL)
set(TOOLCHAIN_PATH "/" CACHE PATH "Path to toolchain native sysroot")
SET(TARGET_SYSROOT_PATH "/" CACHE PATH "Path to toolchain target sysroot")

find_program(EMCC NAMES emcc REQUIRED)
find_program(EMPP NAMES em++ REQUIRED)
find_program(EMAR NAMES emar REQUIRED)
find_program(EMRANLIB NAMES emranlib REQUIRED)

SET(CMAKE_FORCE_C_COMPILER ${EMCC})
SET(CMAKE_FORCE_CXX_COMPILER ${EMPP})
SET(CMAKE_C_COMPILER ${CMAKE_FORCE_C_COMPILER})
SET(CMAKE_CXX_COMPILER ${CMAKE_FORCE_CXX_COMPILER})
set(CMAKE_CXX_COMPILER_AR ${EMAR})
set(CMAKE_AR ${EMAR})
set(CMAKE_CXX_COMPILER_RANLIB ${EMRANLIB})
set(CMAKE_RANLIB ${EMRANLIB})

add_compile_options( -mbulk-memory )
add_compile_options( -sUSE_BOOST_HEADERS=1)

add_link_options( -sALLOW_MEMORY_GROWTH -sMAXIMUM_MEMORY=4294901760 )

set(EMSCRIPTEN_ENV "web")
34 changes: 34 additions & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

cmake_minimum_required(VERSION 3.20)
project(cppdecl)

set(CMAKE_CXX_STANDARD 20)


if(CMAKE_CXX_COMPILER MATCHES "/em\\+\\+(-[a-zA-Z0-9.])?$")
message(" * C++ compiler: Emscripten")
set(CMAKE_CXX_COMPILER_ID "Emscripten")
if ("${EMSCRIPTEN_ENV}" STREQUAL "web")
set(CMAKE_EXECUTABLE_SUFFIX ".html")
else()
set(CMAKE_EXECUTABLE_SUFFIX ".js")
endif()
set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN")
else()
message(" * C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()

if ("${EMSCRIPTEN_ENV}" STREQUAL "web")

add_executable(index cppdecl-shell.cpp )
target_include_directories(index PUBLIC ../include)
target_link_options(index PUBLIC --shell-file ${CMAKE_SOURCE_DIR}/cppdecl-shell.html)
target_link_options(index PUBLIC -sEXPORTED_FUNCTIONS=_main,_malloc,_free -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8,lengthBytesUTF8,ccall,cwrap)

else()
add_executable(cppdecl repl.cpp)
target_include_directories(cppdecl PUBLIC ../include)

add_executable(tests tests.cpp)
target_include_directories(tests PUBLIC ../include)
endif()
134 changes: 134 additions & 0 deletions source/cppdecl-shell.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "cppdecl/declarations/parse.h"
#include "cppdecl/declarations/simplify.h"
#include "cppdecl/declarations/to_string.h"
#include "cppdecl/type_name.h"
#include <emscripten/html5.h>
#include <emscripten.h>
#include <sstream>


std::string escape_xml(std::string_view sv) {
std::string result;
result.reserve(sv.size());
for (size_t i = 0; i < sv.size(); i++) {
uint8_t c = sv[i];

if ((c < 32 and c != '\n') or c == 127) {
continue;
}
switch (c) {
case '<':
result += "&lt;";
break;
case '>':
result += "&gt;";
break;
case '&':
result += "&amp;";
break;
case '\n':
result += "<br/>\n";
break;
case '"':
result += "&quot;";
break;
//case ' ':
// result += "&nbsp;";
break;
default:
result += c;
}
}
constexpr std::array<char8_t, 4> lre = {u8"\u202A"}; // Left-to-Right Embedding
constexpr std::array<char8_t, 4> rle = {u8"\u202B"}; // Right-to-Left Embedding
constexpr std::array<char8_t, 4> pdf = {u8"\u202C"}; // Pop Directional Formatting
constexpr std::array<char8_t, 4> lro = {u8"\u202D"}; // Left-to-Right Override
constexpr std::array<char8_t, 4> rlo = {u8"\u202E"}; // Right-to-Left Override
constexpr std::array<char8_t, 4> lri = {u8"\u2066"}; // Left-to-Right isolate
constexpr std::array<char8_t, 4> rli = {u8"\u2067"}; // Right-to-Left isolate
constexpr std::array<char8_t, 4> fsi = {u8"\u2068"}; // First Strong isolate
constexpr std::array<char8_t, 4> pdi = {u8"\u2069"}; // Pop Directional isolate

constexpr std::array<std::array<char8_t, 4>, 9> control = {lre, rle, pdf, lro, rlo, lri, rli, fsi, pdi};
for (auto& sec : control) {
auto bidi = std::string_view(reinterpret_cast<const char*>(sec.data()), sec.size() - 1);
auto pos = result.find(bidi);
while (pos != std::string::npos) {
result.replace(pos, sec.size(), "");
pos = result.find(bidi);
}
}
return result;
}

namespace cppdecl{
void parseText(std::string_view input) {

auto ret = cppdecl::ParseDecl(input, cppdecl::ParseDeclFlags::accept_everything);
std::ostringstream out;

if (auto error = std::get_if<cppdecl::ParseError>(&ret))
{
out << "Parse error: " << error->message << '\n';
}
else
{
if (!input.empty())
out << "Unparsed junk at the end of input.\n";

auto &decl = std::get<cppdecl::MaybeAmbiguousDecl>(ret);

out << "\n--- Parsed to:\n";
out << cppdecl::ToString(decl, {}) << '\n';

cppdecl::MaybeAmbiguousDecl simplified_decl = decl;
cppdecl::Simplify(cppdecl::SimplifyFlags::all, simplified_decl);
if (simplified_decl != decl)
{
out << "\n--- Simplifies to:\n";
out << cppdecl::ToCode(simplified_decl, {}) << '\n';

out << "\n--- The simplified version parses to:\n";
out << cppdecl::ToString(simplified_decl, {}) << '\n';
}
}

auto demangled = out.str();
auto escaped = escape_xml(demangled);
escaped = demangled;
EM_ASM_({ document.getElementById('demangled').value = UTF8ToString($0, $1); }, escaped.data(), escaped.size());
}
}


extern "C" {
EMSCRIPTEN_KEEPALIVE
void parseText(const char* name1, int nlength1) {
cppdecl::parseText(std::string_view(name1, nlength1));
}
}

void init_loop(void*) {
#ifdef __EMSCRIPTEN__
emscripten_cancel_main_loop();

EM_ASM_({
Module.demangleText = Module.cwrap('demangleText', null, [ 'number', 'number' ]);
is_emscripten_initialized = 1;
set_darkmode(darkmode);
if (pending_demangle) {
document.getElementById('mangled').value = pending_demangle;
demangle_text(pending_demangle);
pending_demangle = null;
}

});

#endif
}

int main(int, char**) {

emscripten_set_main_loop_arg(init_loop, nullptr, 0, false);
return 0;
}
94 changes: 94 additions & 0 deletions source/cppdecl-shell.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<!doctype html>
<html lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--
<link href='./favicon.svg' rel='icon' type='image/svg+xml'>
<link href='./favicon.svg' rel='shortcut icon' type='image/svg+xml'>
-->
<title>cppdecl</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="header" class="header">
cppdecl
</div>
<div id="main" >
<div id="mangledDiv">
<form class="mangling_form" id="mangling_form">
<label for="mangled">mangled name:</label>
<input type="text" maxLength="40" size="40" id="mangled" name="mangled" >
<button type="button" id="demangleButton" onclick="demangle_text(document.getElementById('mangled').value)">demangle</button>
</form>
</div>
<div id="demangledDiv">
<textarea readonly rows="4" cols="40" id="demangled" name="demangled">
</textarea>
</div>

<script >
var is_emscripten_initialized = 0;
var pending_demangle=null;
var darkmode = 0;
document.addEventListener('DOMContentLoaded', (event) => {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('darkmode');
darkmode = 1;
} else {
document.body.classList.remove('darkmode');
darkmode = 0;
}

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
if (event.matches) {
document.body.classList.add('darkmode');
darkmode = 1;
} else {
document.body.classList.remove('darkmode');
darkmode = 0;
}

});

window.addEventListener('load', function() {
let mangling_form = document.getElementById('mangling_form');
mangling_form.reset();
document.getElementById('demangled').value = '';

});
const urlParams = new URLSearchParams(window.location.search);
const mangled = urlParams.get('mangled');

if (mangled) {

if (is_emscripten_initialized == 1) {
document.getElementById('mangled').value = mangled;
parse_text(mangled);
} else {
pending_demangle = mangled;
}

}

});



function parse_text(mangled) {

console.log("parse_text", mangled);
const mangledLength = lengthBytesUTF8(mangled) + 1;
const mangledPtr = _malloc(mangledLength);
stringToUTF8(mangled, mangledPtr, mangledLength);

Module.parseText(mangledPtr, mangledLength - 1);
_free(mangledPtr);
}

</script>
{{{ SCRIPT }}}

</body>
</html>