diff --git a/tools/Makefile.host b/tools/Makefile.host index b66c7a1030..862f51606d 100644 --- a/tools/Makefile.host +++ b/tools/Makefile.host @@ -78,14 +78,14 @@ all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \ configure$(HOSTEXEEXT) mkconfig$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \ mksymtab$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkversion$(HOSTEXEEXT) \ cnvwindeps$(HOSTEXEEXT) nxstyle$(HOSTEXEEXT) initialconfig$(HOSTEXEEXT) \ - logparser$(HOSTEXEEXT) gencromfs$(HOSTEXEEXT) + logparser$(HOSTEXEEXT) gencromfs$(HOSTEXEEXT) convert-comments$(HOSTEXEEXT) default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \ cnvwindeps$(HOSTEXEEXT) ifdef HOSTEXEEXT .PHONY: b16 bdf-converter cmpconfig clean configure kconfig2html mkconfig \ mkdeps mksymtab mksyscall mkversion cnvwindeps nxstyle initialconfig \ - logparser gencromfs + logparser gencromfs convert-comments else .PHONY: clean endif @@ -209,6 +209,15 @@ ifdef HOSTEXEEXT gencromfs: gencromfs$(HOSTEXEEXT) endif +# convert-comments - Convert C++-style comments to C-style comments + +convert-comments$(HOSTEXEEXT): convert-comments.c + $(Q) $(HOSTCC) $(HOSTCFLAGS) -o convert-comments$(HOSTEXEEXT) convert-comments.c + +ifdef HOSTEXEEXT +convert-comments: convert-comments$(HOSTEXEEXT) +endif + # cnvwindeps - Convert dependences generated by a Windows native toolchain # for use in a Cygwin/POSIX build environment diff --git a/tools/README.txt b/tools/README.txt index be952fd6f6..f54c1041c5 100644 --- a/tools/README.txt +++ b/tools/README.txt @@ -69,6 +69,13 @@ configure.c, cfgparser.c, and cfgparser.h 2) That path to bin bin/ directory containing mingw-gcc.exe must be included in the PATH variable. +convert-comments.c +------------------ + + Convert C++-style comments to C89 C-style comments. Usage: + + convert-comments + discover.py ----------- diff --git a/tools/convert-comments.c b/tools/convert-comments.c new file mode 100644 index 0000000000..3748c7a266 --- /dev/null +++ b/tools/convert-comments.c @@ -0,0 +1,394 @@ +/**************************************************************************** + * tools/convert-comments.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Preprocessor Definitions + ****************************************************************************/ + +#define LINESIZE 1024 /* Big so that we don't have to bother with range checks */ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char g_lineA[LINESIZE + 3]; +static char g_lineB[LINESIZE + 3]; +static char g_iobuffer[LINESIZE]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv) +{ + char *g_line0; + char *g_line1; + char *ptr; + char *tmpptr; + FILE *instream; + FILE *outstream; + unsigned long lineno = 0; + unsigned int indent; + unsigned int lastindent; + unsigned int nextindent; + unsigned int tmpindent; + bool iscomment; + bool wascomment; + bool willbecomment; + bool isblank; + bool wasblank; + bool willbeblank; + bool willbevalid; + int ret = 1; + + if (argc != 3) + { + fprintf(stderr, "ERROR: Two arguments expected\n"); + return 1; + } + + /* Open the source file read-only */ + + instream = fopen(argv[1], "r"); + if (instream == NULL) + { + fprintf(stderr, "ERROR: Failed to open %s for reading\n", argv[1]); + return 1; + } + + /* Open the destination file write-only */ + + outstream = fopen(argv[2], "w"); + if (outstream == NULL) + { + fprintf(stderr, "ERROR: Failed to open %s for reading\n", argv[2]); + goto errout_with_instream; + } + + /* Prime the pump */ + + g_line0 = g_lineA; + g_line1 = g_lineB; + wasblank = true; + wascomment = false; + lastindent = 0; + + /* Read line n + 1 (for n = 0) */ + + if (fgets(g_line1, LINESIZE, instream) == NULL) + { + fprintf(stderr, "ERROR: File is empty\n"); + goto errout_with_outstream; + } + + /* Skip over leading spaces in line1 n + 1 */ + + for (ptr = g_line1, nextindent = 0; + *ptr != '\0' && *ptr != '\n' && isspace(*ptr); + ptr++, nextindent++) + { + } + + /* Check for a blank line */ + + if (*ptr == '\0' || *ptr == '\n') + { + ptr = g_line1; + ptr[0] = '\n'; + ptr[1] = '\0'; + willbeblank = true; + willbecomment = false; + nextindent = 0; + } + else + { + /* Check for a C++ style comment at this indentation in line n + 1 */ + + willbeblank = false; + willbecomment = strncmp(ptr, "//", 2) == 0; + } + + do + { + /* Swap line n and line n + 1 */ + + ptr = g_line0; + g_line0 = g_line1; /* New line n */ + g_line1 = ptr; /* Will be new line n + 1 */ + + /* Read the new line n + 1 */ + + willbevalid = (fgets(g_line1, LINESIZE, instream) != NULL); + + /* Update info for line 0 */ + + lineno++; + indent = nextindent; + isblank = willbeblank; + iscomment = willbecomment; + + if (willbevalid) + { + /* Strip trailing spaces and carriage returns from line n + 1 */ + + tmpptr = strchr(g_line1, '\r'); + if (tmpptr != NULL) + { + *tmpptr++ = '\n'; + *tmpptr++ = '\0'; + } + else + { + int len = strlen(ptr); + if (len > 0) + { + for (ptr += len - 1; isspace(*ptr); ptr--) + { + ptr[0] = '\n'; + ptr[1] = '\0'; + } + } + } + + /* Skip over leading spaces in line n + 1 */ + + for (ptr = g_line1, nextindent = 0; + *ptr != '\0' && *ptr != '\n' && isspace(*ptr); + ptr++, nextindent++) + { + } + + /* Check for a blank line */ + + if (*ptr == '\0' || *ptr == '\n') + { + ptr = g_line1; + ptr[0] = '\n'; + ptr[1] = '\0'; + willbeblank = true; + willbecomment = false; + nextindent = 0; + } + else + { + /* Check for a C++ style comment at this indentation in line n + 1 */ + + willbeblank = false; + willbecomment = strncmp(ptr, "//", 2) == 0; + } + + /* Check for a C++ style comment at this indentation in line n + 1 */ + + willbecomment = strncmp(ptr, "//", 2) == 0; + } + else + { + willbeblank = true; + willbecomment = false; + nextindent = 0; + } + + /* If current line is not a comment line, then check for a C++ style comment at the + * end of the line. + */ + + if (!iscomment) + { + /* Skip over leading spaces in line n + 1 */ + + for (ptr = g_line0 + indent, tmpindent = indent; + *ptr != '\0' && *ptr != '\n'; + ptr++, tmpindent++) + { + if (ptr[0] == '/' && ptr[1] == '/') + { + indent = tmpindent; + iscomment = true; + wascomment = false; + break; + } + } + } + + printf("*****************************************************************************\n"); + printf("* %5lu. %s\n", lineno, g_line0); + printf("* indent: last=%u curr=%u next=%u\n", + lastindent, indent, nextindent); + printf("* comment: last=%u curr=%u next=%u\n", + wascomment, iscomment, willbecomment); + printf("* blank: last=%u curr=%u next=%u\n", + wasblank, isblank, willbeblank); + printf("*****************************************************************************\n"); + + /* Does line n start with a comment */ + + ptr = g_line0 + indent; + if (iscomment) + { + /* Check for a comment only line that is was not preceded by a + * comment. + */ + + if (ptr[2] == '\n' && !wascomment) + { + /* Output a blank line */ + + fputc('\n', outstream); + } + + /* Did line n - 1 start with a comment? */ + + else if (wascomment) + { + /* Yes.. Change it to a C-style block comment continuation */ + + ptr[0] = ' '; + ptr[1] = '*'; + + /* Write the modified line to the output */ + + (void)fputs(g_line0, outstream); + } + else + { + /* No.. Change it to a C-style opening comment. */ + + ptr[1] = '*'; + + if (!willbecomment) + { + int len; + + /* Remove final linefeed */ + + len = strlen(ptr); + if (len > 0 && ptr[len - 1] == '\n') + { + len--; + } + + /* Close the single line C comment */ + + ptr += len; + *ptr++ = ' '; + *ptr++ = '*'; + *ptr++ = '/'; + *ptr++ = '\n'; + *ptr++ = '\0'; + + iscomment = false; + + /* Write the modified line to the output */ + + (void)fputs(g_line0, outstream); + + /* Closing comment must be followed by a blank line */ + + if (!willbeblank) + { + /* Output a blank line */ + + fputc('\n', outstream); + } + } + else + { + /* Write the modified line to the output */ + + (void)fputs(g_line0, outstream); + } + } + } + else if (wascomment) + { + /* Line n is not a comment, but line n - 1 was. Output a closing on a + * newline at the same indentation. + */ + + memset(g_iobuffer, ' ', LINESIZE); + ptr = g_iobuffer + lastindent + 1; + *ptr++ = '*'; + *ptr++ = '/'; + *ptr++ = '\n'; + *ptr++ = '\0'; + + /* Write the closing line to the output */ + + (void)fputs(g_iobuffer, outstream); + + /* Closing comment must be followed by a blank line */ + + if (!isblank) + { + /* Output a blank line */ + + fputc('\n', outstream); + } + + /* Write the noncomment line to the output */ + + (void)fputs(g_line0, outstream); + } + else + { + /* Write the noncomment line to the output */ + + (void)fputs(g_line0, outstream); + } + + wascomment = iscomment; + wasblank = isblank; + lastindent = indent; + } + while (willbevalid); + + ret = 0; + +errout_with_outstream: + fclose(outstream); + +errout_with_instream: + fclose(instream); + return ret; +}