You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
12 KiB
352 lines
12 KiB
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Struct Visualization</title>
|
|
<base href="/">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
</head>
|
|
<style>
|
|
:root {
|
|
--r1: pink;
|
|
--r2: blue;
|
|
--r3: magenta;
|
|
--r4: yellow;
|
|
--r5: cyan;
|
|
--r6: orange;
|
|
--r7: lime;
|
|
--r8: olive;
|
|
}
|
|
|
|
*::before,
|
|
*::after,
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html, body {
|
|
min-height: 100vh;
|
|
height: 100vh;
|
|
overscroll-behavior: none;
|
|
background: #F0EAD6;
|
|
padding-top: 10px;
|
|
|
|
direction: ltr;
|
|
font: 16px HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;
|
|
}
|
|
|
|
.struct-info {
|
|
padding: 0 20px 20px 20px;
|
|
border-bottom: 1px solid silver;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.struct-info-declaration {
|
|
position: absolute;
|
|
font-family: monospace;
|
|
min-width: min-content;
|
|
max-width: 20em;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
font-size: 0.9em;
|
|
transform: translateX(calc(50% - 10px));
|
|
color: black;
|
|
font-weight: normal;
|
|
}
|
|
.struct-info-declaration-name {
|
|
font: 16px HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;
|
|
}
|
|
|
|
.struct-info-declaration-top {
|
|
top: -30px;
|
|
}
|
|
.struct-info-declaration-bottom {
|
|
bottom: -30px;
|
|
}
|
|
|
|
.struct-info-byte-row-ellipsis {
|
|
position: absolute;
|
|
right: 1em;
|
|
}
|
|
|
|
.struct-info-byte-rows {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: flex-start;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.struct-info-byte-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
flex-direction: row;
|
|
justify-content: flex-start;
|
|
align-items: center;
|
|
}
|
|
|
|
.struct-info-bytegroup {
|
|
margin: 2em 0;
|
|
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
flex-direction: row;
|
|
justify-content: flex-start;
|
|
align-items: center;
|
|
}
|
|
|
|
.struct-info-bytegroup:hover {
|
|
background-color: orange;
|
|
|
|
.struct-info-declaration {
|
|
font-weight: bold;
|
|
color: orange;
|
|
}
|
|
}
|
|
|
|
.struct-info-header {
|
|
font-weight: bold;
|
|
font-family: monospace;
|
|
}
|
|
|
|
.struct-info-byte {
|
|
position: relative;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border: 1px solid black;
|
|
width: 30px;
|
|
height: 45px;
|
|
}
|
|
.struct-info-byte-alignment {
|
|
background-color: seagreen;
|
|
opacity: 0.4;
|
|
}
|
|
.struct-info-byte-first {
|
|
border-left-width: 3px;
|
|
}
|
|
.struct-info-byte-unknown {
|
|
border-left-width: 3px;
|
|
background-color: maroon;
|
|
font-weight: bold;
|
|
color: white;
|
|
}
|
|
.struct-info-byte-counted-ellipsis {
|
|
background-color: #808000;
|
|
font-weight: bold;
|
|
}
|
|
.struct-info-byte-ellipsis {
|
|
background-color: #400000;
|
|
font-weight: bold;
|
|
color: white;
|
|
}
|
|
|
|
dialog {
|
|
position: sticky;
|
|
top: 50vh;
|
|
left: 50vw;
|
|
transform: translate(-50%, -50%);
|
|
padding: 20px;
|
|
|
|
border: none;
|
|
border-radius: 3px;
|
|
background-color: #F0EAD6;
|
|
box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);
|
|
|
|
max-width: 80vw;
|
|
max-height: 80vh;
|
|
}
|
|
|
|
input:not([type=checkbox]):not([type=radio]) {
|
|
display: block;
|
|
height: 2em;
|
|
}
|
|
|
|
p {
|
|
margin: 20px;
|
|
}
|
|
|
|
input[type=checkbox] {
|
|
width: 1.2rem;
|
|
height: 1.2rem;
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
}
|
|
|
|
label > input {
|
|
margin: 5px 15px 15px 15px;
|
|
}
|
|
|
|
.fix-missing-declaration-dialog-footer {
|
|
width: 100%;
|
|
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
button {
|
|
width: 10rem;
|
|
height: 2rem;
|
|
}
|
|
|
|
.help-idk {
|
|
color: darkslategray;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.help-idk-container {
|
|
width: 100%;
|
|
margin-bottom: 10px;
|
|
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: flex-end;
|
|
align-items: center;
|
|
}
|
|
</style>
|
|
|
|
<body>
|
|
<dialog
|
|
id="fix-missing-declaration-dialog"
|
|
>
|
|
<p>What's the size and alignment of this type on your architecture?</p>
|
|
<div class="help-idk-container">
|
|
<p class="help-idk">
|
|
Help, I don't know!
|
|
</p>
|
|
</div>
|
|
|
|
<label>
|
|
It's a bitfield!
|
|
<input
|
|
type="checkbox"
|
|
/>
|
|
</label>
|
|
|
|
<label>
|
|
size (in bytes)
|
|
<input
|
|
type="number"
|
|
min="1"
|
|
value="8"
|
|
/>
|
|
</label>
|
|
|
|
<label>
|
|
alignment (in bytes)
|
|
<input
|
|
type="number"
|
|
value="8"
|
|
/>
|
|
</label>
|
|
|
|
<footer class="fix-missing-declaration-dialog-footer">
|
|
<button
|
|
onclick="fixMissingDeclDialog.close()"
|
|
>
|
|
Confirm
|
|
</button>
|
|
</footer>
|
|
</dialog>
|
|
<script defer>
|
|
const fixMissingDeclDialog = document.getElementById("fix-missing-declaration-dialog");
|
|
|
|
function createWithClasses(e, ...classes) {
|
|
const elem = document.createElement(e);
|
|
elem.classList.add(...classes);
|
|
return elem;
|
|
}
|
|
|
|
function alignForward(a, b) {
|
|
|
|
}
|
|
|
|
function renderStruct(structInfo, containingElement) {
|
|
const div = createWithClasses("div", "struct-info");
|
|
|
|
const structInfoHeader = createWithClasses("label", "struct-info-header");
|
|
structInfoHeader.innerText = `struct ${structInfo.name} - alias: ${structInfo.alias}`;
|
|
div.appendChild(structInfoHeader);
|
|
|
|
for (let i = 0; i < structInfo.declarations.length; i++) {
|
|
const decl = structInfo.declarations[i];
|
|
|
|
const position = i % 2 == 0;
|
|
const positionClass = position ? "struct-info-declaration-top" : "struct-info-declaration-bottom";
|
|
let bytesInStructSoFar = 0;
|
|
|
|
if (decl.size === -1) {
|
|
const byteGroup = createWithClasses("struct-info-bytegroup");
|
|
byteGroup.onclick = fixMissingDeclDialog.showMoodal();
|
|
|
|
|
|
const unknownByte = createWithClasses("div", "struct-info-byte", "struct-info-byte-unknown");
|
|
unknownByte.innerText = "?";
|
|
byteGroup.appendChild(unknownByte);
|
|
|
|
const declaration = createWithClasses("div", "struct-info-declaration", positionClass);
|
|
declaration.innerHTML = `${decl.type} <span class="struct-info-declaration-name">${decl.name}</span>`;
|
|
unknownByte.appendChild(declaration);
|
|
|
|
const ellipsisByte = createWithClasses("div", "struct-info-byte", "struct_info_byte_ellipsis");
|
|
ellipsisByte.innerText = "...";
|
|
byteGroup.appendChild(ellipsisByte);
|
|
|
|
div.appendChild(byteGroup);
|
|
} else {
|
|
// find if we need to align this field - pad some alignment bytes visually if we do.
|
|
const aligned = alignForward(bytesInStructSoFar, decl.align);
|
|
const needsAlign = aligned !== bytesInStructSoFar;
|
|
if (needsAlign) {
|
|
//sb_concatf("%s", "<div class='struct-info-bytegroup'>");
|
|
//for (int a = 0; a < (aligned - bytesInStructSoFar); a++) {
|
|
// sb_concatf("%s", "<div class='struct-info-byte struct-info-byte-alignment'></div>");
|
|
//}
|
|
//sb_concatf("%s", "</div>");
|
|
//bytesInStructSoFar += aligned - bytesInStructSoFar;
|
|
}
|
|
|
|
// now for the bytes representing the actual field.
|
|
//sb_concatf("%s", "<div class='struct-info-bytegroup'>");
|
|
//for (int b = 0; b < decl->size; b++) {
|
|
// if (b == 0) {
|
|
// sb_concatf(
|
|
// "<div class='struct-info-byte struct-info-byte-first'>"
|
|
// "<div class='struct-info-declaration %s'>"
|
|
// "%s <span class='struct-info-declaration-name'>%s</span>"
|
|
// "</div>"
|
|
// "</div>"
|
|
// , positionClass, decl->type, decl->name);
|
|
// } else {
|
|
// sb_concatf("%s", "<div class='struct-info-byte'></div>");
|
|
// }
|
|
//}
|
|
//bytesInStructSoFar += decl->size;
|
|
//sb_concatf("%s", "</div>"); // end bytegroup
|
|
}
|
|
//sb_concatf("%s", "</div></div>");
|
|
}
|
|
|
|
containingElement.appendChild(div);
|
|
}
|
|
|
|
function renderAllStructs() {
|
|
for (let i = 0; i < window.structs.length; i++) {
|
|
const structInfo = structs[i];
|
|
renderStruct(structInfo, document.body);
|
|
}
|
|
}
|
|
</script>
|
|
<!-- c code will place a script tag containing all of the data structures in JSON format, and terminate the body and html tags -->
|
|
|
|
|
|
<script>
|
|
window.structs = JSON.parse(`[
|
|
{"name":"Dummy","alias":"","filename":"main.c","lineNumber":78,"lineOffset":7,"size":13,"declarations":[{"type": "char*","name": "p","size": "8","align": "8","isBitfield": false},{"type": "char","name": "c","size": "1","align": "1","isBitfield": false},{"type": "int","name": "x","size": "4","align": "4","isBitfield": false}]},{"name":"Declaration","alias":"","filename":"main.c","lineNumber":162,"lineOffset":7,"size":145,"declarations":[{"type": "char","name": "type[64]","size": "64","align": "1","isBitfield": false},{"type": "char","name": "name[64]","size": "64","align": "1","isBitfield": false},{"type": "ssize_t","name": "size","size": "8","align": "8","isBitfield": false},{"type": "ssize_t","name": "align","size": "8","align": "8","isBitfield": false},{"type": "bool","name": "isBitfield","size": "1","align": "1","isBitfield": false}]},{"name":"StructInfo","alias":"","filename":"main.c","lineNumber":170,"lineOffset":7,"size":151,"declarations":[{"type": "char","name": "name[64]","size": "64","align": "1","isBitfield": false},{"type": "char","name": "alias[64]","size": "64","align": "1","isBitfield": false},{"type": "char*","name": "filename","size": "8","align": "8","isBitfield": false},{"type": "int","name": "lineNumber","size": "4","align": "4","isBitfield": false},{"type": "ssize_t","name": "size","size": "8","align": "8","isBitfield": false},{"type": "struct Declaration","name": "declarations[16]","size": "-1","align": "-1","isBitfield": false},{"type": "int","name": "numDeclarations","size": "4","align": "4","isBitfield": false}]},{"name":"Array","alias":"","filename":"main.c","lineNumber":214,"lineOffset":7,"size":16,"declarations":[{"type": "unsigned int","name": "length","size": "4","align": "4","isBitfield": false},{"type": "unsigned int","name": "capacity","size": "4","align": "4","isBitfield": false},{"type": "void*","name": "data","size": "8","align": "8","isBitfield": false}]},{"name":"TableEntry","alias":"TableEntry","filename":"table.h","lineNumber":27,"lineOffset":15,"size":23,"declarations":[{"type": "struct TableEntry*","name": "next","size": "8","align": "8","isBitfield": false},{"type": "char key","name": "TABLE_KEY_SIZE","size": "-1","align": "-1","isBitfield": false},{"type": "ssize_t","name": "size","size": "8","align": "8","isBitfield": false},{"type": "ssize_t","name": "align","size": "8","align": "8","isBitfield": false}]},{"name":"Table","alias":"Table","filename":"table.h","lineNumber":35,"lineOffset":15,"size":8,"declarations":[{"type": "TableEntry**","name": "entries","size": "8","align": "8","isBitfield": false}]},{"name":"","alias":"stb_lexer","filename":"stb_c_lexer.h","lineNumber":113,"lineOffset":0,"size":88,"declarations":[{"type": "char*","name": "input_stream","size": "8","align": "8","isBitfield": false},{"type": "char*","name": "eof","size": "8","align": "8","isBitfield": false},{"type": "char*","name": "parse_point","size": "8","align": "8","isBitfield": false},{"type": "char*","name": "string_storage","size": "8","align": "8","isBitfield": false},{"type": "int","name": "string_storage_len","size": "4","align": "4","isBitfield": false},{"type": "char*","name": "where_firstchar","size": "8","align": "8","isBitfield": false},{"type": "char*","name": "where_lastchar","size": "8","align": "8","isBitfield": false},{"type": "long","name": "token","size": "8","align": "8","isBitfield": false},{"type": "double","name": "real_number","size": "8","align": "8","isBitfield": false},{"type": "long","name": "int_number","size": "8","align": "8","isBitfield": false},{"type": "char*","name": "string","size": "8","align": "8","isBitfield": false},{"type": "int","name": "string_len","size": "4","align": "4","isBitfield": false}]},{"name":"","alias":"stb_lex_location","filename":"stb_c_lexer.h","lineNumber":134,"lineOffset":0,"size":8,"declarations":[{"type": "int","name": "line_number","size": "4","align": "4","isBitfield": false},{"type": "int","name": "line_offset","size": "4","align": "4","isBitfield": false}]}]`);renderAllStructs();
|
|
</script></body></html>
|