2023-03-16 23:09:19 -07:00
|
|
|
#include "Spec.hpp"
|
|
|
|
|
|
|
|
#include "IO.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Spec
|
|
|
|
{
|
|
|
|
ct uw Array_Reserve_Num = zpl_kilobytes(4);
|
|
|
|
ct uw Token_Max_Length = zpl_kilobytes(1);
|
|
|
|
|
|
|
|
namespace StaticData
|
|
|
|
{
|
2023-03-25 19:44:36 -07:00
|
|
|
// Custom comment signatures not supported yet (only C/C++ comments for now)
|
|
|
|
bool Ignore_Comments = false;
|
|
|
|
|
2023-03-16 23:09:19 -07:00
|
|
|
Array_Entry Ignore_Includes;
|
|
|
|
Array_Entry Ignore_Words;
|
|
|
|
Array_Entry Ignore_Regexes;
|
|
|
|
Array_Entry Ignore_Namespaces;
|
|
|
|
|
|
|
|
Array_Entry Includes;
|
|
|
|
Array_Entry Words;
|
|
|
|
Array_Entry Regexes;
|
|
|
|
Array_Entry Namespaces;
|
|
|
|
|
|
|
|
u32 Sig_Smallest = Token_Max_Length;
|
|
|
|
}
|
|
|
|
using namespace StaticData;
|
|
|
|
|
|
|
|
void cleanup()
|
|
|
|
{
|
|
|
|
zpl_array_free( Ignore_Includes );
|
|
|
|
zpl_array_free( Ignore_Words );
|
|
|
|
zpl_array_free( Ignore_Namespaces );
|
|
|
|
zpl_array_free( Includes );
|
|
|
|
zpl_array_free( Words );
|
|
|
|
zpl_array_free( Namespaces );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Helper function for process().
|
|
|
|
forceinline
|
2023-03-18 00:10:43 -07:00
|
|
|
void find_next_token( Tok& type, zpl_string& token, char*& line, u32& length )
|
2023-03-16 23:09:19 -07:00
|
|
|
{
|
|
|
|
zpl_string_clear( token );
|
|
|
|
length = 0;
|
|
|
|
|
2023-03-18 00:10:43 -07:00
|
|
|
#define current line[length]
|
|
|
|
if (type == Tok::Include)
|
2023-03-16 23:09:19 -07:00
|
|
|
{
|
2023-03-18 00:10:43 -07:00
|
|
|
// Allows for '.'
|
|
|
|
while ( zpl_char_is_alphanumeric( current )
|
|
|
|
|| current == '_'
|
2023-03-25 19:44:36 -07:00
|
|
|
|| current == '.'
|
|
|
|
|| current == '/'
|
|
|
|
|| current == '\\' )
|
2023-03-18 00:10:43 -07:00
|
|
|
{
|
|
|
|
length++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while ( zpl_char_is_alphanumeric( current ) || current == '_' )
|
|
|
|
{
|
|
|
|
length++;
|
|
|
|
}
|
2023-03-16 23:09:19 -07:00
|
|
|
}
|
2023-03-18 00:10:43 -07:00
|
|
|
#undef current
|
2023-03-16 23:09:19 -07:00
|
|
|
|
|
|
|
if ( length == 0 )
|
|
|
|
{
|
|
|
|
fatal("Failed to find valid initial token");
|
|
|
|
}
|
|
|
|
|
|
|
|
token = zpl_string_append_length( token, line, length );
|
|
|
|
line += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
void parse()
|
|
|
|
{
|
|
|
|
static zpl_string token = zpl_string_make_reserve( g_allocator, zpl_kilobytes(1));
|
|
|
|
|
|
|
|
static bool Done = false;
|
|
|
|
if (Done)
|
|
|
|
{
|
|
|
|
zpl_array_clear( Ignore_Includes );
|
|
|
|
zpl_array_clear( Ignore_Words );
|
|
|
|
zpl_array_clear( Ignore_Namespaces );
|
|
|
|
zpl_array_clear( Includes );
|
|
|
|
zpl_array_clear( Words );
|
|
|
|
zpl_array_clear( Namespaces );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Done = true;
|
|
|
|
|
|
|
|
zpl_array_init_reserve( Ignore_Includes, zpl_heap(), Array_Reserve_Num );
|
|
|
|
zpl_array_init_reserve( Ignore_Words, zpl_heap(), Array_Reserve_Num );
|
|
|
|
zpl_array_init_reserve( Ignore_Namespaces, zpl_heap(), Array_Reserve_Num );
|
|
|
|
zpl_array_init_reserve( Includes, zpl_heap(), Array_Reserve_Num );
|
|
|
|
zpl_array_init_reserve( Words, zpl_heap(), Array_Reserve_Num );
|
|
|
|
zpl_array_init_reserve( Namespaces, zpl_heap(), Array_Reserve_Num );
|
|
|
|
}
|
|
|
|
|
|
|
|
Array_Line lines = IO::get_specification();
|
|
|
|
|
|
|
|
sw left = zpl_array_count( lines );
|
|
|
|
|
|
|
|
if ( left == 0 )
|
|
|
|
{
|
|
|
|
fatal("Spec::parse: lines array imporoperly setup");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip the first line as its the version number and we only support __VERSION 1.
|
|
|
|
left--;
|
|
|
|
lines++;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
char* line = * lines;
|
|
|
|
|
|
|
|
// Ignore line if its a comment
|
|
|
|
if ( line[0] == '/' && line[1] == '/')
|
|
|
|
{
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove indent
|
|
|
|
{
|
|
|
|
while ( zpl_char_is_space( line[0] ) )
|
|
|
|
line++;
|
|
|
|
|
|
|
|
if ( line[0] == '\0' )
|
|
|
|
{
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-18 00:10:43 -07:00
|
|
|
u32 length = 0;
|
2023-03-16 23:09:19 -07:00
|
|
|
Tok type = Tok::Num_Tok;
|
|
|
|
bool ignore = false;
|
|
|
|
Entry entry {};
|
|
|
|
|
2023-03-18 00:10:43 -07:00
|
|
|
|
|
|
|
// Find a valid token
|
|
|
|
find_next_token( type, token, line, length );
|
|
|
|
|
2023-03-16 23:09:19 -07:00
|
|
|
// Will be reguarded as an ignore.
|
|
|
|
if ( is_tok( Tok::Not, token, length ))
|
|
|
|
{
|
|
|
|
ignore = true;
|
|
|
|
|
|
|
|
while ( zpl_char_is_space( line[0] ) )
|
|
|
|
line++;
|
|
|
|
|
|
|
|
if ( line[0] == '\0' )
|
|
|
|
{
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the category token
|
2023-03-18 00:10:43 -07:00
|
|
|
find_next_token( type, token, line, length );
|
2023-03-16 23:09:19 -07:00
|
|
|
}
|
|
|
|
|
2023-03-25 19:44:36 -07:00
|
|
|
if ( is_tok( Tok::Comment, token, length ) )
|
|
|
|
{
|
|
|
|
// Custom comment signatures not supported yet (only C/C++ comments for now)
|
|
|
|
Ignore_Comments = true;
|
|
|
|
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( is_tok( Tok::Word, token, length ) )
|
2023-03-16 23:09:19 -07:00
|
|
|
{
|
|
|
|
type = Tok::Word;
|
|
|
|
}
|
|
|
|
else if ( is_tok( Tok::Namespace, token, length ) )
|
|
|
|
{
|
|
|
|
type = Tok::Namespace;
|
|
|
|
}
|
|
|
|
else if ( is_tok( Tok::Include, token, length ))
|
|
|
|
{
|
|
|
|
type = Tok::Include;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log_fmt( "Sec::Parse - Unsupported keyword: %s on line: %d", token, zpl_array_count(lines) - left );
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the first argument
|
|
|
|
while ( zpl_char_is_space( line[0] ) )
|
|
|
|
line++;
|
|
|
|
|
|
|
|
if ( line[0] == '\0' )
|
|
|
|
{
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
2023-03-18 00:10:43 -07:00
|
|
|
|
|
|
|
find_next_token( type, token, line, length );
|
2023-03-16 23:09:19 -07:00
|
|
|
|
|
|
|
// First argument is signature.
|
|
|
|
entry.Sig = zpl_string_make_length( g_allocator, token, length );
|
|
|
|
|
|
|
|
if ( length < StaticData::Sig_Smallest )
|
|
|
|
StaticData::Sig_Smallest = length;
|
|
|
|
|
|
|
|
if ( line[0] == '\0' || ignore )
|
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case Tok::Word:
|
|
|
|
if ( ignore)
|
|
|
|
zpl_array_append( Ignore_Words, entry );
|
|
|
|
|
|
|
|
else
|
|
|
|
zpl_array_append( Words, entry );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tok::Namespace:
|
|
|
|
if ( ignore)
|
|
|
|
zpl_array_append( Ignore_Namespaces, entry );
|
|
|
|
|
|
|
|
else
|
|
|
|
zpl_array_append( Namespaces, entry );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tok::Include:
|
|
|
|
if ( ignore)
|
|
|
|
zpl_array_append( Ignore_Includes, entry );
|
|
|
|
|
|
|
|
else
|
|
|
|
zpl_array_append( Includes, entry );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for second argument indicator
|
|
|
|
{
|
|
|
|
bool bSkip = false;
|
|
|
|
|
|
|
|
while ( line[0] != ',' )
|
|
|
|
{
|
|
|
|
if ( line[0] == '\0' )
|
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case Tok::Word:
|
|
|
|
zpl_array_append( Words, entry );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tok::Namespace:
|
|
|
|
zpl_array_append( Namespaces, entry );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tok::Include:
|
|
|
|
zpl_array_append( Includes, entry );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
bSkip = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
line++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bSkip )
|
|
|
|
{
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Eat the argument delimiter.
|
|
|
|
line++;
|
|
|
|
|
|
|
|
// Remove spacing
|
|
|
|
{
|
|
|
|
bool bSkip = true;
|
|
|
|
|
|
|
|
while ( zpl_char_is_space( line[0] ) )
|
|
|
|
line++;
|
|
|
|
|
|
|
|
if ( line[0] == '\0' )
|
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case Tok::Word:
|
|
|
|
zpl_array_append( Words, entry );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tok::Namespace:
|
|
|
|
zpl_array_append( Namespaces, entry );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Tok::Include:
|
|
|
|
zpl_array_append( Includes, entry );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-18 00:10:43 -07:00
|
|
|
find_next_token( type, token, line, length );
|
2023-03-16 23:09:19 -07:00
|
|
|
|
|
|
|
// Second argument is substitute.
|
|
|
|
entry.Sub = zpl_string_make_length( g_allocator, token, length );
|
|
|
|
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
case Tok::Word:
|
|
|
|
zpl_array_append( Words, entry );
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case Tok::Namespace:
|
|
|
|
zpl_array_append( Namespaces, entry );
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case Tok::Include:
|
|
|
|
zpl_array_append( Includes, entry );
|
|
|
|
lines++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while ( --left );
|
2023-03-25 19:44:36 -07:00
|
|
|
|
|
|
|
Spec::Entry* ignore = Spec::Ignore_Includes;
|
|
|
|
sw ignores_left = zpl_array_count( Spec::Ignore_Includes);
|
|
|
|
|
|
|
|
zpl_printf("\nIgnores: ");
|
|
|
|
for ( ; ignores_left; ignores_left--, ignore++ )
|
|
|
|
{
|
|
|
|
zpl_printf("\n%s", ignore->Sig);
|
|
|
|
}
|
|
|
|
zpl_printf("\n");
|
2023-03-16 23:09:19 -07:00
|
|
|
}
|
|
|
|
}
|