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