mirror of
https://github.com/Noratrieb/womangling.git
synced 2026-01-14 08:55:03 +01:00
init
This commit is contained in:
commit
e6201286ac
4 changed files with 351 additions and 0 deletions
93
index.css
Normal file
93
index.css
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
--color-primary: rebeccapurple;
|
||||
--color-white: white;
|
||||
--color-error: red;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100vw;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 50rem;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.start-button {
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.lessons-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.step {
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid black;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.code {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form[data-challenge] > .error {
|
||||
margin-top: 10px;
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.quiz-section {
|
||||
border: 2px var(--color-primary) solid;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.submit-challenge {
|
||||
height: 2.5rem;
|
||||
|
||||
background-color: var(--color-primary);
|
||||
color: var(--color-white);
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
padding: 0px 10px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(in oklab, var(--color-primary), white 15%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: color-mix(in oklab, var(--color-primary), grey 80%);
|
||||
cursor: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.quiz-input {
|
||||
height: 2.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
52
index.html
Normal file
52
index.html
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="index.css" />
|
||||
<title>Womangling</title>
|
||||
</head>
|
||||
<body>
|
||||
<main class="main">
|
||||
<div class="content">
|
||||
<h1>Learn C++ Itanium Mangling</h1>
|
||||
<noscript>
|
||||
<p>
|
||||
Warning: You have JavaScript disabled While the content is still
|
||||
viewable, interactive exercises will not work. Consider enabling
|
||||
JavaScript for this website.
|
||||
</p>
|
||||
</noscript>
|
||||
<p>
|
||||
This website will teach you C++ Itanium Name Mangling. Itanium-style
|
||||
mangling is used on a lot of platforms, including Linux.
|
||||
</p>
|
||||
<p>
|
||||
Since C++ mangling (the entire ABI) is considered stable today, you
|
||||
will be able to use this knowledge forever!
|
||||
</p>
|
||||
<p>
|
||||
This website consists of many lessons, each teaching you something new
|
||||
about C++ Itanium Mangling. There will be many interactive quizzes at
|
||||
each step to test your knowledge.
|
||||
</p>
|
||||
<div class="center">
|
||||
<ol class="lessons-list">
|
||||
<li class="lesson-list-item">
|
||||
<a href="/lesson-0.html">C names</a>
|
||||
</li>
|
||||
<li class="lesson-list-item">
|
||||
<a href="/lesson.html?lesson=1">Arguments and Return Types</a>
|
||||
</li>
|
||||
<li class="lesson-list-item">
|
||||
<a href="/lesson.html?lesson=2">More Integers</a>
|
||||
</li>
|
||||
<li class="lesson-list-item">
|
||||
<a href="/lesson.html?lesson=3">Namespaces</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
112
lesson-0.html
Normal file
112
lesson-0.html
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="index.css" />
|
||||
<title>Womangling</title>
|
||||
</head>
|
||||
<body>
|
||||
<main class="main">
|
||||
<div class="content" id="content-area">
|
||||
<h1>Learn C++ Itanium Mangling</h1>
|
||||
<h2>Lesson 1: Intro and C names</h2>
|
||||
<noscript>
|
||||
<p>
|
||||
Warning: You have JavaScript disabled While the content is still
|
||||
viewable, interactive exercises will not work. Consider enabling
|
||||
JavaScript for this website.
|
||||
</p>
|
||||
</noscript>
|
||||
|
||||
<section data-step="0" class="step">
|
||||
<p>
|
||||
Welcome to the interactive Itanium C++ mangling learning website! In
|
||||
this course you will learn everything there is to know about Itanium
|
||||
C++ Mangling, especially the things you've never wanted to know.
|
||||
</p>
|
||||
<p>
|
||||
For every exercise, there will be a small quiz. If you complete the
|
||||
quiz, you can continue
|
||||
</p>
|
||||
<div class="quiz-section">
|
||||
<p>To complete the first quiz, press the button below.</p>
|
||||
<form data-challenge="1">
|
||||
<button
|
||||
data-challenge-submit="1"
|
||||
class="submit-challenge"
|
||||
type="submit"
|
||||
>
|
||||
Complete first challenge!
|
||||
</button>
|
||||
<div class="error"></div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
<section data-step="1" class="step">
|
||||
<p>
|
||||
Congrats, you just completed your first challenge! Good job. So,
|
||||
let's start with the mangling. Before diving too deep into the
|
||||
innards of Itanium Mangling, let's get more familiar with the way
|
||||
this works by mangling something trivial: a C function. C functions
|
||||
are traditionally not mangled (*this is not always fully true on all
|
||||
platforms). The simplest possible C function takes no arguments and
|
||||
returns no value. For C it doesn't actually matter what the
|
||||
parameters or return value are, since there is no mangling.
|
||||
</p>
|
||||
<p>
|
||||
To reference this function in C++, we use an
|
||||
<code>extern "C"</code> block.
|
||||
</p>
|
||||
<pre class="code">
|
||||
extern "C" {
|
||||
void hello() {}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Because no mangling is applied to the identifier at all, the symbol
|
||||
for this function will simply be <code>hello</code>.
|
||||
</p>
|
||||
<p>
|
||||
Similarly, a more complex example would be the following function:
|
||||
</p>
|
||||
<pre class="code">
|
||||
extern "C" {
|
||||
int main(int argc, char* argv[]) {}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
But once again, the symbol name will simply be
|
||||
<code>main</code> because no mangling is applied.
|
||||
</p>
|
||||
<div class="quiz-section">
|
||||
<p>What is the mangled symbol of the following function?</p>
|
||||
<pre class="code">
|
||||
extern "C" {
|
||||
long long meow(long long argument, long long second) { /* too long */ }
|
||||
}
|
||||
</pre>
|
||||
<form data-challenge="2" data-answer="meow">
|
||||
<input class="quiz-input" />
|
||||
<button
|
||||
data-challenge-submit="2"
|
||||
class="submit-challenge"
|
||||
type="submit"
|
||||
>
|
||||
Answer
|
||||
</button>
|
||||
<div class="error"></div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
<section data-step="2" class="step">
|
||||
<p>meow meow meow!!</p>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
window.LESSON = 0;
|
||||
</script>
|
||||
<script type="module" src="./lessons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
94
lessons.js
Normal file
94
lessons.js
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
let step = 0;
|
||||
|
||||
const parseIntThrow = (s) => {
|
||||
const i = parseInt(s, 10);
|
||||
if (Number.isNaN(i)) {
|
||||
throw new Error(`Cannot parse integer for ${s}`);
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
const setShowHiddenSteps = () => {
|
||||
const elements = document.querySelectorAll("[data-step]");
|
||||
for (const element of elements) {
|
||||
const sectionStep = parseIntThrow(element.dataset.step);
|
||||
if (sectionStep > step) {
|
||||
element.classList.add("hidden");
|
||||
} else {
|
||||
element.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const rerender = () => {
|
||||
setShowHiddenSteps();
|
||||
const buttonElements = document.querySelectorAll(
|
||||
"button[data-challenge-submit]"
|
||||
);
|
||||
for (const element of buttonElements) {
|
||||
const elemStep = parseIntThrow(element.dataset.challengeSubmit);
|
||||
element.disabled = elemStep <= step;
|
||||
}
|
||||
};
|
||||
|
||||
const setStep = (newStep) => {
|
||||
if (newStep > step) {
|
||||
step = newStep;
|
||||
rerender();
|
||||
}
|
||||
};
|
||||
|
||||
const initButtons = () => {
|
||||
const formElements = document.querySelectorAll("form[data-challenge]");
|
||||
for (const element of formElements) {
|
||||
const step = parseIntThrow(element.dataset.challenge);
|
||||
|
||||
const error = element.querySelector(".error");
|
||||
if (!error) {
|
||||
alert(`The step ${step} is missing an error div!`);
|
||||
}
|
||||
|
||||
element.addEventListener("submit", (e) => {
|
||||
e.preventDefault(e);
|
||||
|
||||
error.innerText = "";
|
||||
|
||||
const answer = element.dataset.answer;
|
||||
if (!answer) {
|
||||
setStep(step);
|
||||
return;
|
||||
}
|
||||
|
||||
const input = e.target[0];
|
||||
|
||||
const value = input.value;
|
||||
if (value === answer) {
|
||||
setStep(step);
|
||||
return;
|
||||
}
|
||||
|
||||
// Wrong answer :(
|
||||
const incorrectTries = parseIntThrow(error.dataset.errors ?? "0");
|
||||
const messages = [
|
||||
"This is not the right answer, please try again.",
|
||||
"This is still not the right answer, please try again.",
|
||||
`This is still not the right answer, please try again. Tip: The answer is ${answer.length} characters long`,
|
||||
`The right answer was: '${answer}'. Enter it to finish this step.`,
|
||||
];
|
||||
if (incorrectTries >= messages.length) {
|
||||
input.value = answer;
|
||||
setStep(step); // just give up and finish lol
|
||||
return;
|
||||
}
|
||||
error.innerText = messages[incorrectTries];
|
||||
error.dataset.errors = incorrectTries + 1;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
initButtons();
|
||||
rerender();
|
||||
};
|
||||
|
||||
init();
|
||||
Loading…
Add table
Add a link
Reference in a new issue