makesdna: fix parsing 'const', 'struct', 'unsigned' as a prefix

DNA parsing assumed any identifier which starts with
(`struct`, `unsigned`, `const`) was that identifier.

So a struct called `constTest foo;` would be parsed as `est foo;`.

Add utility function to check identifiers are not
part of a larger identifier.

This also supports skipping these identifiers in any order.

Reviewed By: LazyDodo

Ref D11837
This commit is contained in:
2021-07-07 12:35:03 +10:00
parent f85ef3d442
commit 31e6f0dc7a

View File

@@ -43,6 +43,7 @@
#define DNA_DEPRECATED_ALLOW
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -272,6 +273,37 @@ void print_struct_sizes(void);
* Make DNA string (write to file).
* \{ */
static bool match_identifier_with_len(const char *str,
const char *identifier,
const size_t identifier_len)
{
if (strncmp(str, identifier, identifier_len) == 0) {
/* Check `str` isn't a prefix to a longer identifier. */
if (isdigit(str[identifier_len]) || isalpha(str[identifier_len]) ||
(str[identifier_len] == '_')) {
return false;
}
return true;
}
return false;
}
static bool match_identifier(const char *str, const char *identifier)
{
const size_t identifier_len = strlen(identifier);
return match_identifier_with_len(str, identifier, identifier_len);
}
static bool match_identifier_and_advance(char **str_ptr, const char *identifier)
{
const size_t identifier_len = strlen(identifier);
if (match_identifier_with_len(*str_ptr, identifier, identifier_len)) {
(*str_ptr) += identifier_len;
return true;
}
return false;
}
static const char *version_struct_static_from_alias(const char *str)
{
const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_static_from_alias, str);
@@ -619,7 +651,7 @@ static int preprocess_include(char *maindata, const int maindata_len)
else if (cp[-1] == '*' && cp[0] == ' ') {
/* pointers with a space */
} /* skip special keywords */
else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) {
else if (match_identifier(cp, "DNA_DEPRECATED")) {
/* single values are skipped already, so decrement 1 less */
a -= 13;
cp += 13;
@@ -721,7 +753,7 @@ static int convert_include(const char *filename)
md1++;
/* we've got a struct name when... */
if (strncmp(md1 - 7, "struct", 6) == 0) {
if (match_identifier(md1 - 7, "struct")) {
const int strct = add_type(md1, 0);
if (strct == -1) {
@@ -756,14 +788,22 @@ static int convert_include(const char *filename)
/* skip when it says 'struct' or 'unsigned' or 'const' */
if (*md1) {
if (strncmp(md1, "struct", 6) == 0) {
md1 += 7;
}
if (strncmp(md1, "unsigned", 8) == 0) {
md1 += 9;
}
if (strncmp(md1, "const", 5) == 0) {
md1 += 6;
const char *md1_prev = md1;
while (match_identifier_and_advance(&md1, "struct") ||
match_identifier_and_advance(&md1, "unsigned") ||
match_identifier_and_advance(&md1, "const")) {
if (UNLIKELY(!ELEM(*md1, '\0', ' '))) {
/* This will happen with: `unsigned(*value)[3]` which isn't supported. */
fprintf(stderr,
"File '%s' contains non white space character "
"\"%c\" after identifier \"%s\"\n",
filename,
*md1,
md1_prev);
return 1;
}
/* Skip ' ' or '\0'. */
md1++;
}
/* we've got a type! */