Added assembly header detection.

This commit is contained in:
Johanne Schock 2020-03-14 14:36:47 +01:00 committed by patacongo
parent 23db3b2a48
commit cdf615855a

View File

@ -116,6 +116,10 @@ enum pptype_e
{
PPLINE_NONE = 0,
PPLINE_DEFINE,
PPLINE_IF,
PPLINE_ELIF,
PPLINE_ELSE,
PPLINE_ENDIF,
PPLINE_OTHER
};
@ -526,6 +530,8 @@ int main(int argc, char **argv, char **envp)
int dnest; /* Data declaration nesting level on this line */
int prevdnest; /* Data declaration nesting level on the previous line */
int pnest; /* Parenthesis nesting level on this line */
int ppifnest; /* #if nesting level on this line */
int inasm; /* > 0: Within #ifdef __ASSEMBLY__ */
int comment_lineno; /* Line on which the last comment was closed */
int blank_lineno; /* Line number of the last blank line */
int noblank_lineno; /* A blank line is not needed after this line */
@ -643,6 +649,8 @@ int main(int argc, char **argv, char **envp)
bnest = 0; /* Brace nesting level on this line */
dnest = 0; /* Data declaration nesting level on this line */
pnest = 0; /* Parenthesis nesting level on this line */
ppifnest = 0; /* #if nesting level on this line */
inasm = 0; /* > 0: Within #ifdef __ASSEMBLY__ */
comment_lineno = -1; /* Line on which the last comment was closed */
blank_lineno = -1; /* Line number of the last blank line */
noblank_lineno = -1; /* A blank line is not needed after this line */
@ -851,71 +859,147 @@ int main(int argc, char **argv, char **envp)
* line.
*/
ii = indent + 1;
if (ppline == PPLINE_NONE)
{
/* Skip to the pre-processor command following the '#' */
for (ii = indent + 1;
line[ii] != '\0' && isspace(line[ii]);
ii++)
{
}
while (line[ii] != '\0' && isspace(line[ii]))
{
ii++;
}
if (line[ii] != '\0')
{
/* Make sure that pre-processor definitions are all in
* the pre-processor definitions section.
*/
if (line[ii] != '\0')
{
/* Make sure that pre-processor definitions are all in
* the pre-processor definitions section.
*/
ppline = PPLINE_OTHER;
ppline = PPLINE_OTHER;
if (strncmp(&line[ii], "define", 6) == 0)
{
ppline = PPLINE_DEFINE;
if (strncmp(&line[ii], "define", 6) == 0)
{
ppline = PPLINE_DEFINE;
if (g_section != PRE_PROCESSOR_DEFINITIONS)
{
/* A complication is the header files always have
* the idempotence guard definitions before the
* "Pre-processor Definitions section".
*/
if (g_section != PRE_PROCESSOR_DEFINITIONS)
{
/* A complication is the header files always have
* the idempotence guard definitions before the
* "Pre-processor Definitions section".
*/
if (g_section == NO_SECTION &&
g_file_type != C_HEADER)
{
/* Only a warning because there is some usage
* of define outside the Pre-processor
* Definitions section which is justifiable.
* Should be manually checked.
*/
if (g_section == NO_SECTION &&
g_file_type != C_HEADER)
{
/* Only a warning because there is some usage
* of define outside the Pre-processor
* Definitions section which is justifiable.
* Should be manually checked.
*/
WARN("#define outside of 'Pre-processor "
"Definitions' section",
lineno, ii);
}
}
}
WARN("#define outside of 'Pre-processor "
"Definitions' section",
lineno, ii);
}
}
}
/* Make sure that files are included only in the Included
* Files section.
*/
/* Make sure that files are included only in the Included
* Files section.
*/
else if (strncmp(&line[ii], "include", 7) == 0)
{
if (g_section != INCLUDED_FILES)
{
/* Only a warning because there is some usage of
* include outside the Included Files section
* which may be is justifiable. Should be
* manually checked.
*/
else if (strncmp(&line[ii], "include", 7) == 0)
{
if (g_section != INCLUDED_FILES)
{
/* Only a warning because there is some usage of
* include outside the Included Files section
* which may be is justifiable. Should be
* manually checked.
*/
WARN("#include outside of 'Included Files' "
"section",
lineno, ii);
}
}
}
WARN("#include outside of 'Included Files' "
"section",
lineno, ii);
}
}
else if (strncmp(&line[ii], "if", 2) == 0)
{
ppifnest++;
ppline = PPLINE_IF;
ii += 2;
}
else if (strncmp(&line[ii], "elif", 4) == 0)
{
if (ppifnest == inasm)
{
inasm = 0;
}
ppline = PPLINE_ELIF;
ii += 4;
}
else if (strncmp(&line[ii], "else", 4) == 0)
{
if (ppifnest == inasm)
{
inasm = 0;
}
ppline = PPLINE_ELSE;
}
else if (strncmp(&line[ii], "endif", 4) == 0)
{
if (ppifnest == inasm)
{
inasm = 0;
}
ppifnest--;
ppline = PPLINE_ENDIF;
}
}
}
if (ppline == PPLINE_IF || ppline == PPLINE_ELIF)
{
int bdef = 0;
if (strncmp(&line[ii], "def", 3) == 0)
{
bdef = 1;
ii += 3;
}
else
{
while (line[ii] != '\0' && isspace(line[ii]))
{
ii++;
}
if (strncmp(&line[ii], "defined", 7) == 0)
{
bdef = 1;
ii += 7;
}
}
if (bdef)
{
while (line[ii] != '\0' &&
(isspace(line[ii]) || line[ii] == '('))
{
ii++;
}
if (strncmp(&line[ii], "__ASSEMBLY__", 12) == 0)
{
inasm = ppifnest;
}
}
}
/* Check if the next line will be a continuation of the pre-
@ -968,10 +1052,12 @@ int main(int argc, char **argv, char **envp)
rhcomment = -1;
if (ncomment > 0 && (strncmp(&line[ii], "if", 2) == 0 ||
strncmp(&line[ii], "el", 2) == 0))
if (ncomment > 0 &&
(ppline == PPLINE_IF ||
ppline == PPLINE_ELSE ||
ppline == PPLINE_ELIF))
{
/* in #if... and #el.. */
/* in #if... and #el... */
ERROR("No multiline comment right of code allowed here",
lineno, n);
@ -1047,175 +1133,178 @@ int main(int argc, char **argv, char **envp)
* example.
*/
else if (strncmp(&line[indent], "auto ", 5) == 0 ||
strncmp(&line[indent], "bool ", 5) == 0 ||
strncmp(&line[indent], "char ", 5) == 0 ||
strncmp(&line[indent], "CODE ", 5) == 0 ||
strncmp(&line[indent], "const ", 6) == 0 ||
strncmp(&line[indent], "double ", 7) == 0 ||
strncmp(&line[indent], "struct ", 7) == 0 ||
strncmp(&line[indent], "struct\n", 7) == 0 || /* May be unnamed */
strncmp(&line[indent], "enum ", 5) == 0 ||
strncmp(&line[indent], "extern ", 7) == 0 ||
strncmp(&line[indent], "EXTERN ", 7) == 0 ||
strncmp(&line[indent], "FAR ", 4) == 0 ||
strncmp(&line[indent], "float ", 6) == 0 ||
strncmp(&line[indent], "int ", 4) == 0 ||
strncmp(&line[indent], "int16_t ", 8) == 0 ||
strncmp(&line[indent], "int32_t ", 8) == 0 ||
strncmp(&line[indent], "long ", 5) == 0 ||
strncmp(&line[indent], "off_t ", 6) == 0 ||
strncmp(&line[indent], "register ", 9) == 0 ||
strncmp(&line[indent], "short ", 6) == 0 ||
strncmp(&line[indent], "signed ", 7) == 0 ||
strncmp(&line[indent], "size_t ", 7) == 0 ||
strncmp(&line[indent], "ssize_t ", 8) == 0 ||
strncmp(&line[indent], "static ", 7) == 0 ||
strncmp(&line[indent], "time_t ", 7) == 0 ||
strncmp(&line[indent], "typedef ", 8) == 0 ||
strncmp(&line[indent], "uint8_t ", 8) == 0 ||
strncmp(&line[indent], "uint16_t ", 9) == 0 ||
strncmp(&line[indent], "uint32_t ", 9) == 0 ||
strncmp(&line[indent], "union ", 6) == 0 ||
strncmp(&line[indent], "union\n", 6) == 0 || /* May be unnamed */
strncmp(&line[indent], "unsigned ", 9) == 0 ||
strncmp(&line[indent], "void ", 5) == 0 ||
strncmp(&line[indent], "volatile ", 9) == 0)
else if (inasm == 0)
{
/* Check if this is extern "C"; We don't typically indent following
* this.
*/
if (strncmp(&line[indent], "extern \"C\"", 10) == 0)
if (strncmp(&line[indent], "auto ", 5) == 0 ||
strncmp(&line[indent], "bool ", 5) == 0 ||
strncmp(&line[indent], "char ", 5) == 0 ||
strncmp(&line[indent], "CODE ", 5) == 0 ||
strncmp(&line[indent], "const ", 6) == 0 ||
strncmp(&line[indent], "double ", 7) == 0 ||
strncmp(&line[indent], "struct ", 7) == 0 ||
strncmp(&line[indent], "struct\n", 7) == 0 || /* May be unnamed */
strncmp(&line[indent], "enum ", 5) == 0 ||
strncmp(&line[indent], "extern ", 7) == 0 ||
strncmp(&line[indent], "EXTERN ", 7) == 0 ||
strncmp(&line[indent], "FAR ", 4) == 0 ||
strncmp(&line[indent], "float ", 6) == 0 ||
strncmp(&line[indent], "int ", 4) == 0 ||
strncmp(&line[indent], "int16_t ", 8) == 0 ||
strncmp(&line[indent], "int32_t ", 8) == 0 ||
strncmp(&line[indent], "long ", 5) == 0 ||
strncmp(&line[indent], "off_t ", 6) == 0 ||
strncmp(&line[indent], "register ", 9) == 0 ||
strncmp(&line[indent], "short ", 6) == 0 ||
strncmp(&line[indent], "signed ", 7) == 0 ||
strncmp(&line[indent], "size_t ", 7) == 0 ||
strncmp(&line[indent], "ssize_t ", 8) == 0 ||
strncmp(&line[indent], "static ", 7) == 0 ||
strncmp(&line[indent], "time_t ", 7) == 0 ||
strncmp(&line[indent], "typedef ", 8) == 0 ||
strncmp(&line[indent], "uint8_t ", 8) == 0 ||
strncmp(&line[indent], "uint16_t ", 9) == 0 ||
strncmp(&line[indent], "uint32_t ", 9) == 0 ||
strncmp(&line[indent], "union ", 6) == 0 ||
strncmp(&line[indent], "union\n", 6) == 0 || /* May be unnamed */
strncmp(&line[indent], "unsigned ", 9) == 0 ||
strncmp(&line[indent], "void ", 5) == 0 ||
strncmp(&line[indent], "volatile ", 9) == 0)
{
externc_lineno = lineno;
}
/* bfunctions: True: Processing private or public functions.
* bnest: Brace nesting level on this line
* dnest: Data declaration nesting level on this line
*/
/* REVISIT: Also picks up function return types */
/* REVISIT: Logic problem for nested data/function declarations */
if ((!bfunctions || bnest > 0) && dnest == 0)
{
dnest = 1;
}
/* Check for multiple definitions of variables on the line.
* Ignores declarations within parentheses which are probably
* formal parameters.
*/
if (pnest == 0)
{
int tmppnest;
/* Note, we have not yet parsed each character on the line so
* a comma have have been be preceded by '(' on the same line.
* We will have parse up to any comma to see if that is the
* case.
/* Check if this is extern "C"; We don't typically indent
* following this.
*/
for (i = indent, tmppnest = 0;
line[i] != '\n' && line[i] != '\0';
i++)
if (strncmp(&line[indent], "extern \"C\"", 10) == 0)
{
if (tmppnest == 0 && line[i] == ',')
externc_lineno = lineno;
}
/* bfunctions: True: Processing private or public functions.
* bnest: Brace nesting level on this line
* dnest: Data declaration nesting level on this line
*/
/* REVISIT: Also picks up function return types */
/* REVISIT: Logic problem for nested data/function declarations */
if ((!bfunctions || bnest > 0) && dnest == 0)
{
dnest = 1;
}
/* Check for multiple definitions of variables on the line.
* Ignores declarations within parentheses which are probably
* formal parameters.
*/
if (pnest == 0)
{
int tmppnest;
/* Note, we have not yet parsed each character on the line so
* a comma have have been be preceded by '(' on the same line.
* We will have parse up to any comma to see if that is the
* case.
*/
for (i = indent, tmppnest = 0;
line[i] != '\n' && line[i] != '\0';
i++)
{
ERROR("Multiple data definitions", lineno, i + 1);
break;
}
else if (line[i] == '(')
{
tmppnest++;
}
else if (line[i] == ')')
{
if (tmppnest < 1)
if (tmppnest == 0 && line[i] == ',')
{
/* We should catch this later */
ERROR("Multiple data definitions", lineno, i + 1);
break;
}
else if (line[i] == '(')
{
tmppnest++;
}
else if (line[i] == ')')
{
if (tmppnest < 1)
{
/* We should catch this later */
break;
}
tmppnest--;
}
else if (line[i] == ';')
{
/* Break out if the semicolon terminates the
* declaration is found. Avoids processing any
* righthand comments in most cases.
*/
break;
}
tmppnest--;
}
else if (line[i] == ';')
{
/* Break out if the semicolon terminates the
* declaration is found. Avoids processing any
* righthand comments in most cases.
*/
break;
}
}
}
}
/* Check for a keyword indicating the beginning of a statement.
* REVISIT: This, obviously, will not detect statements that do not
* begin with a C keyword (such as assignment statements).
*/
/* Check for a keyword indicating the beginning of a statement.
* REVISIT: This, obviously, will not detect statements that do not
* begin with a C keyword (such as assignment statements).
*/
else if (strncmp(&line[indent], "break ", 6) == 0 ||
strncmp(&line[indent], "case ", 5) == 0 ||
#if 0 /* Part of switch */
strncmp(&line[indent], "case ", 5) == 0 ||
#endif
strncmp(&line[indent], "continue ", 9) == 0 ||
else if (strncmp(&line[indent], "break ", 6) == 0 ||
strncmp(&line[indent], "case ", 5) == 0 ||
#if 0 /* Part of switch */
strncmp(&line[indent], "case ", 5) == 0 ||
#endif
strncmp(&line[indent], "continue ", 9) == 0 ||
#if 0 /* Part of switch */
strncmp(&line[indent], "default ", 8) == 0 ||
#endif
strncmp(&line[indent], "do ", 3) == 0 ||
strncmp(&line[indent], "else ", 5) == 0 ||
strncmp(&line[indent], "goto ", 5) == 0 ||
strncmp(&line[indent], "if ", 3) == 0 ||
strncmp(&line[indent], "return ", 7) == 0 ||
#if 0 /* Doesn't follow pattern */
strncmp(&line[indent], "switch ", 7) == 0 ||
#endif
strncmp(&line[indent], "while ", 6) == 0)
{
bstatm = true;
}
#if 0 /* Part of switch */
strncmp(&line[indent], "default ", 8) == 0 ||
#endif
strncmp(&line[indent], "do ", 3) == 0 ||
strncmp(&line[indent], "else ", 5) == 0 ||
strncmp(&line[indent], "goto ", 5) == 0 ||
strncmp(&line[indent], "if ", 3) == 0 ||
strncmp(&line[indent], "return ", 7) == 0 ||
#if 0 /* Doesn't follow pattern */
strncmp(&line[indent], "switch ", 7) == 0 ||
#endif
strncmp(&line[indent], "while ", 6) == 0)
{
bstatm = true;
}
/* Spacing works a little differently for and switch statements */
/* Spacing works a little differently for and switch statements */
else if (strncmp(&line[indent], "for ", 4) == 0)
{
bfor = true;
bstatm = true;
}
else if (strncmp(&line[indent], "switch ", 7) == 0)
{
bswitch = true;
}
else if (strncmp(&line[indent], "for ", 4) == 0)
{
bfor = true;
bstatm = true;
}
else if (strncmp(&line[indent], "switch ", 7) == 0)
{
bswitch = true;
}
/* Also check for C keywords with missing white space */
/* Also check for C keywords with missing white space */
else if (strncmp(&line[indent], "do(", 3) == 0 ||
strncmp(&line[indent], "if(", 3) == 0 ||
strncmp(&line[indent], "while(", 6) == 0)
{
ERROR("Missing whitespace after keyword", lineno, n);
bstatm = true;
}
else if (strncmp(&line[indent], "for(", 4) == 0)
{
ERROR("Missing whitespace after keyword", lineno, n);
bfor = true;
bstatm = true;
}
else if (strncmp(&line[indent], "switch(", 7) == 0)
{
ERROR("Missing whitespace after keyword", lineno, n);
bswitch = true;
else if (strncmp(&line[indent], "do(", 3) == 0 ||
strncmp(&line[indent], "if(", 3) == 0 ||
strncmp(&line[indent], "while(", 6) == 0)
{
ERROR("Missing whitespace after keyword", lineno, n);
bstatm = true;
}
else if (strncmp(&line[indent], "for(", 4) == 0)
{
ERROR("Missing whitespace after keyword", lineno, n);
bfor = true;
bstatm = true;
}
else if (strncmp(&line[indent], "switch(", 7) == 0)
{
ERROR("Missing whitespace after keyword", lineno, n);
bswitch = true;
}
}
/* STEP 3: Parse each character on the line */
@ -1590,14 +1679,14 @@ int main(int argc, char **argv, char **envp)
bquote = false;
}
/* The reset of the line is only examined of we are not in a comment
* or a string.
/* The rest of the line is only examined of we are not in a comment,
* in a string or in assembly.
*
* REVISIT: Should still check for whitespace at the end of the
* line.
*/
if (ncomment == 0 && !bstring)
if (ncomment == 0 && !bstring && inasm == 0)
{
switch (line[n])
{