static size_t indexHtmlSize = 0; static char* indexHtml = NULL; #define sb_concatf(fmt, ...) \ if ((sbc - sbi) < 1024) { \ sbc *= 1.5; \ stringBuffer = realloc(stringBuffer, sbc); \ } \ if ((result = snprintf(stringBuffer + sbi, sbc - sbi, fmt, ##__VA_ARGS__)) > 0) sbi += result; \ else die("fatal error concating to string"); static void outputHtml() { static int sbi = 0; static int sbc = 50 * 1024; static char* stringBuffer = NULL; if (stringBuffer == NULL) stringBuffer = malloc(sizeof(char) * sbc); if (indexHtml == NULL) indexHtml = readWholeFile("base-index.html", &indexHtmlSize); int result = 0; sb_concatf("%s", indexHtml); for (int i = 0; i < numAllStructs; i++) { struct StructInfo *structInfo = allStructs + i; printStructInfo(structInfo); ssize_t byteCounter = 0; sb_concatf( "
" "" "
" , structInfo->name, structInfo->alias); for (int d = 0; d < structInfo->numDeclarations; d++) { struct Declaration *decl = structInfo->declarations + d; bool truncate32 = false; if (decl->size > 32) { truncate32 = true; } sb_concatf("%s", "
"); bool first = (d % 2) == 0; const char* positionClass = first ? "struct-info-declaration-top" : "struct-info-declaration-bottom"; if (decl->size == -1) { sb_concatf( "
?" "
" "%s %s" "
" "
" "
...
" , positionClass, decl->type, decl->name); } else { for (int b = 0; b < decl->size; b++) { if (b == 0) { sb_concatf( "
" "
" "%s %s" "
" "
" , positionClass, decl->type, decl->name); } else if (truncate32 && b == 32) { sb_concatf("
...[%ld]
", decl->size - b); break; } else { sb_concatf("%s", "
"); } } } sb_concatf("%s", "
"); } sb_concatf("%s", "
"); } // don't forget the closing body and html tags sb_concatf("%s", ""); // write the index.html file out to disk FILE* fp = fopen("index.html", "wb"); if (fp == NULL) { die("failed to open the file index.html"); } size_t writtenCount = fwrite(stringBuffer, 1, sbi, fp); fclose(fp); if (writtenCount != sbi) { die("wrote only partially"); } }