Add a way to read comments in header file
This commit is contained in:
parent
e2a3fc5bed
commit
0d0009ad5c
@ -11,8 +11,8 @@ REM Oi Use CPU Intrinsics
|
||||
REM Z7 Combine multi-debug files to one debug file
|
||||
REM wd4201 Nonstandard extension used: nameless struct/union
|
||||
REM Tp Treat header file as CPP source file
|
||||
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /D DQN_INSPECT_EXECUTABLE_IMPLEMENTATION /Tp ../Code/DqnInspect.h /link /nologo
|
||||
DqnInspect.exe ..\Data\DqnInspect_TestData.h > ..\Data\DqnInspect_TestDataGenerated.cpp
|
||||
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /wd4201 /D DQN_HEADER_IMPLEMENTATION /Tp ../Code/DqnHeader.h /link /nologo
|
||||
DqnHeader.exe ..\Code\Dqn.h > ..\Code\DqnHeader_Generated.h
|
||||
|
||||
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /wd4201 /D DQN_IMPLEMENTATION ../Code/Dqn_UnitTests.cpp /link /nologo
|
||||
cl /MT /EHa /GR- /Od /Oi /Z7 /W4 /WX /P /wd4201 /D DQN_IMPLEMENTATION ../Code/Dqn_UnitTests.cpp /link /nologo
|
||||
popd
|
||||
|
664
Code/Dqn.h
664
Code/Dqn.h
File diff suppressed because it is too large
Load Diff
157
Code/DqnHeader.h
Normal file
157
Code/DqnHeader.h
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef DQN_HEADER_H
|
||||
#define DQN_HEADER_H
|
||||
#define DQN_HEADER_COPY_PROTOTYPE(func_return, func_name_and_types) func_return func_name_and_types
|
||||
#endif /* DQN_HEADER_H */
|
||||
|
||||
#ifdef DQN_HEADER_IMPLEMENTATION
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS // NOTE: Undefined at end of file
|
||||
#include <stddef.h>
|
||||
|
||||
#define DQN_IMPLEMENTATION
|
||||
#include "Dqn.h"
|
||||
|
||||
char const *Dqn_Header__ParseFunctionReturnType(char const *ptr, isize *len)
|
||||
{
|
||||
char const *result = Dqn_StrSkipWhitespace(ptr);
|
||||
isize result_len = 0;
|
||||
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function return type
|
||||
{
|
||||
if (ptr[0] == '<' || ptr[0] == '>')
|
||||
{
|
||||
if (ptr[0] == '<') scope++;
|
||||
else scope--;
|
||||
continue;
|
||||
}
|
||||
else if (ptr[0] == ',')
|
||||
{
|
||||
if (scope != 0) continue;
|
||||
result_len = static_cast<int>(ptr - result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) *len = result_len;
|
||||
return result;
|
||||
}
|
||||
|
||||
char const *Dqn_Header__ParseFunctionNameAndParameters(char const *ptr, isize *len)
|
||||
{
|
||||
char const *result = ptr;
|
||||
int result_len = 0;
|
||||
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function name and parameters
|
||||
{
|
||||
if (ptr[0] == '(') scope++;
|
||||
else if (ptr[0] == ')')
|
||||
{
|
||||
if (scope-- != 0) continue;
|
||||
result_len = static_cast<int>(ptr - result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*len = result_len;
|
||||
return result;
|
||||
}
|
||||
|
||||
char const *Dqn_Header__ParseFunctionComment(char const *ptr, isize *len)
|
||||
{
|
||||
while (ptr[0] != '"') ptr++;
|
||||
ptr++;
|
||||
|
||||
char const *result = ptr;
|
||||
isize result_len = 0;
|
||||
for (;;)
|
||||
{
|
||||
while (ptr[0] != '"')
|
||||
ptr++;
|
||||
|
||||
if (ptr[-1] != '\\')
|
||||
{
|
||||
result_len = ptr - result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*len = result_len;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
{
|
||||
fprintf(stdout, "DqnHeader Usage: %s [<source code filename>, ...]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dqn_MemArena arena = {};
|
||||
for (isize arg_index = 1; arg_index < argc; ++arg_index)
|
||||
{
|
||||
char const *file = argv[arg_index];
|
||||
isize buf_size = 0;
|
||||
char *buf = Dqn_FileReadWithArena(&arena, file, &buf_size);
|
||||
if (!buf)
|
||||
{
|
||||
fprintf(stderr, "Failed to read file: %s\n", file);
|
||||
continue;
|
||||
}
|
||||
|
||||
char constexpr HEADER_COPY_PROTOTYPE[] = "DQN_HEADER_COPY_PROTOTYPE";
|
||||
char constexpr HEADER_COMMENT[] = "// @";
|
||||
|
||||
enum struct FindString
|
||||
{
|
||||
HeaderPrototype,
|
||||
HeaderComment,
|
||||
Count
|
||||
};
|
||||
|
||||
char const *find_list[] = {HEADER_COPY_PROTOTYPE, HEADER_COMMENT};
|
||||
isize constexpr find_string_lens[] = {
|
||||
Dqn_CharCountI(HEADER_COPY_PROTOTYPE),
|
||||
Dqn_CharCountI(HEADER_COMMENT),
|
||||
};
|
||||
|
||||
char const *ptr = buf;
|
||||
char const *ptr_end = buf + buf_size;
|
||||
isize ptr_len = buf_size;
|
||||
isize matched_find_index = -1;
|
||||
for (char const *token = Dqn_StrMultiFind(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len);
|
||||
token;
|
||||
token = Dqn_StrMultiFind(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len))
|
||||
{
|
||||
if (matched_find_index == (isize)FindString::HeaderPrototype)
|
||||
{
|
||||
ptr = token + find_string_lens[matched_find_index] + 1 /*macro start parenthesis*/;
|
||||
isize func_type_len = 0;
|
||||
char const *func_type = Dqn_Header__ParseFunctionReturnType(ptr, &func_type_len);
|
||||
|
||||
ptr = func_type + func_type_len + 1; // Ptr is at macro comma, skip the comma
|
||||
ptr = Dqn_StrSkipWhitespace(ptr);
|
||||
isize func_name_len = 0;
|
||||
char const *func_name = Dqn_Header__ParseFunctionNameAndParameters(ptr, &func_name_len);
|
||||
|
||||
ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren
|
||||
fprintf(stdout, "%.*s %.*s;\n", (int)func_type_len, func_type, (int)func_name_len, func_name);
|
||||
}
|
||||
else if (matched_find_index == (isize)FindString::HeaderComment)
|
||||
{
|
||||
char const *comment_start = token;
|
||||
ptr = token;
|
||||
while (ptr[0] != '\n' && ptr[0] != '\r')
|
||||
ptr++;
|
||||
|
||||
isize comment_len = ptr - comment_start;
|
||||
fprintf(stdout, "%.*s\n", (int)comment_len, comment_start);
|
||||
ptr = comment_start + comment_len;
|
||||
}
|
||||
|
||||
ptr_len = ptr_end - ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef _CRT_SECURE_NO_WARNINGS
|
||||
#endif /* DQN_HEADER_IMPLEMENTATION */
|
@ -1,6 +1,3 @@
|
||||
#define DQN_HEADER_COPY_PROTOTYPE_AND_COMMENT(func_comment, func_return, func_name_and_types) func_return func_name_and_types
|
||||
#define DQN_HEADER_COPY_PROTOTYPE(func_return, func_name_and_types) func_return func_name_and_types
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include "Dqn.h"
|
||||
|
||||
@ -421,176 +418,11 @@ FILE_SCOPE void UnitTests()
|
||||
}
|
||||
}
|
||||
|
||||
char *Dqn_ReadFileWithArena(Dqn_MemArena *arena, char const *file, isize *file_size)
|
||||
{
|
||||
FILE *file_handle = fopen(file, "rb");
|
||||
fseek(file_handle, 0, SEEK_END);
|
||||
usize file_size_ = ftell(file_handle);
|
||||
rewind(file_handle);
|
||||
|
||||
auto *result = (char *)MEM_ARENA_ALLOC(arena, file_size_ + 1);
|
||||
DQN_ASSERT(result);
|
||||
result[file_size_] = 0;
|
||||
|
||||
if (fread(result, file_size_, 1, file_handle) != 1)
|
||||
{
|
||||
fprintf(stderr, "Failed to fread: %zu bytes into buffer from file: %s\n", file_size_, file);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (file_size) *file_size = file_size_;
|
||||
return result;
|
||||
}
|
||||
|
||||
char *Dqn_StrFind(char *buf, char const *find, isize buf_len = -1, isize find_len = -1)
|
||||
{
|
||||
if (find_len == 0) return nullptr;
|
||||
if (buf_len < 0) buf_len = (isize)strlen(buf);
|
||||
if (find_len < 0) find_len = (isize)strlen(find);
|
||||
|
||||
char *buf_end = buf + buf_len;
|
||||
char *result = nullptr;
|
||||
for (; *buf; ++buf)
|
||||
{
|
||||
isize remaining = static_cast<isize>(buf_end - buf);
|
||||
if (remaining < find_len) break;
|
||||
|
||||
if (strncmp(buf, find, find_len) == 0)
|
||||
{
|
||||
result = buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char *Dqn_StrSkipWhitespace(char *buf)
|
||||
{
|
||||
while (buf && (buf[0] == '\r' || buf[0] == '\t' || buf[0] == '\n' || buf[0] == ' '))
|
||||
buf++;
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *ParseFunctionReturnType(char *ptr, isize *len)
|
||||
{
|
||||
char *result = Dqn_StrSkipWhitespace(ptr);
|
||||
isize result_len = 0;
|
||||
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function return type
|
||||
{
|
||||
if (ptr[0] == '<' || ptr[0] == '>')
|
||||
{
|
||||
if (ptr[0] == '<') scope++;
|
||||
else scope--;
|
||||
continue;
|
||||
}
|
||||
else if (ptr[0] == ',')
|
||||
{
|
||||
if (scope != 0) continue;
|
||||
result_len = static_cast<int>(ptr - result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) *len = result_len;
|
||||
return result;
|
||||
}
|
||||
|
||||
char *ParseFunctionNameAndParameters(char *ptr, isize *len)
|
||||
{
|
||||
char *result = ptr;
|
||||
int result_len = 0;
|
||||
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function name and parameters
|
||||
{
|
||||
if (ptr[0] == '(') scope++;
|
||||
else if (ptr[0] == ')')
|
||||
{
|
||||
if (scope-- != 0) continue;
|
||||
result_len = static_cast<int>(ptr - result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*len = result_len;
|
||||
return result;
|
||||
}
|
||||
|
||||
char *ParseFunctionComment(char *ptr, isize *len)
|
||||
{
|
||||
while (ptr[0] != '"') ptr++;
|
||||
ptr++;
|
||||
|
||||
char *result = ptr;
|
||||
isize result_len = 0;
|
||||
for (;;)
|
||||
{
|
||||
while (ptr[0] != '"')
|
||||
ptr++;
|
||||
|
||||
if (ptr[-1] != '\\')
|
||||
{
|
||||
result_len = ptr - result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*len = result_len;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int main(char *argv[], int argc)
|
||||
{
|
||||
(void)argv; (void)argc;
|
||||
UnitTests();
|
||||
|
||||
Dqn_MemArena arena = {};
|
||||
isize buf_size = 0;
|
||||
char *buf = Dqn_ReadFileWithArena(&arena, "../Code/Dqn.h", &buf_size);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
char constexpr HEADER_COPY_PROTOTYPE[] = "DQN_HEADER_COPY_PROTOTYPE";
|
||||
char constexpr HEADER_COPY_PROTOTYPE_AND_COMMENT[] = "DQN_HEADER_COPY_PROTOTYPE_AND_COMMENT";
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
char *ptr = buf;
|
||||
char *ptr_end = buf + buf_size;
|
||||
isize ptr_len = buf_size;
|
||||
for (char *token = Dqn_StrFind(ptr, HEADER_COPY_PROTOTYPE, ptr_len, Dqn_CharCountI(HEADER_COPY_PROTOTYPE));
|
||||
token;
|
||||
ptr_len = ptr_end - ptr, token = Dqn_StrFind(ptr, HEADER_COPY_PROTOTYPE, ptr_len))
|
||||
{
|
||||
ptr = token;
|
||||
bool prototype_and_comment = (strncmp(token, HEADER_COPY_PROTOTYPE_AND_COMMENT, Dqn_CharCountI(HEADER_COPY_PROTOTYPE_AND_COMMENT)) == 0);
|
||||
if (prototype_and_comment)
|
||||
{
|
||||
ptr += Dqn_CharCount(HEADER_COPY_PROTOTYPE_AND_COMMENT) + 1 /*macro start parenthesis*/;
|
||||
|
||||
isize comment_len = 0;
|
||||
char *comment = ParseFunctionComment(ptr, &comment_len);
|
||||
ptr = comment + comment_len;
|
||||
while (ptr[0] != ',') ptr++;
|
||||
ptr++;
|
||||
|
||||
fprintf(stdout, "%.*s\n", (int)comment_len, comment);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += Dqn_CharCount(HEADER_COPY_PROTOTYPE) + 1 /*macro start parenthesis*/;
|
||||
}
|
||||
|
||||
isize func_type_len = 0;
|
||||
char *func_type = ParseFunctionReturnType(ptr, &func_type_len);
|
||||
|
||||
ptr = func_type + func_type_len + 1; // Ptr is at macro comma, skip the comma
|
||||
ptr = Dqn_StrSkipWhitespace(ptr);
|
||||
isize func_name_len = 0;
|
||||
char *func_name = ParseFunctionNameAndParameters(ptr, &func_name_len);
|
||||
|
||||
ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren
|
||||
fprintf(stdout, "%.*s %.*s\n", (int)func_type_len, func_type, (int)func_name_len, func_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user