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