330 lines
8.9 KiB
C
330 lines
8.9 KiB
C
/****************************************************************************
|
|
* tools/mksymtab.c
|
|
*
|
|
* Copyright (C) 2012, 2015 Gregory Nutt. All rights reserved.
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* 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 <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
#include "csvparser.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define MAX_HEADER_FILES 500
|
|
#define SYMTAB_NAME "g_symtab"
|
|
#define NSYMBOLS_NAME "g_nsymbols"
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static const char *g_hdrfiles[MAX_HEADER_FILES];
|
|
static int nhdrfiles;
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
static void show_usage(const char *progname)
|
|
{
|
|
fprintf(stderr,
|
|
"USAGE:\n");
|
|
fprintf(stderr,
|
|
"%s [-d] <cvs-file> <symtab-file> [<symtab-name> [<nsymbols-name>]]\n\n",
|
|
progname);
|
|
fprintf(stderr,
|
|
"Where:\n\n");
|
|
fprintf(stderr,
|
|
" <cvs-file> : The path to the input CSV file (required)\n");
|
|
fprintf(stderr,
|
|
" <symtab-file> : The path to the output symbol table file\n");
|
|
fprintf(stderr,
|
|
"(required)\n");
|
|
fprintf(stderr,
|
|
" <symtab-name> : Optional name for the symbol table variable\n");
|
|
fprintf(stderr,
|
|
" Default: \"%s\"\n", SYMTAB_NAME);
|
|
fprintf(stderr,
|
|
" <nsymbols-name> : Optional name for the symbol table variable\n");
|
|
fprintf(stderr,
|
|
" Default: \"%s\"\n", NSYMBOLS_NAME);
|
|
fprintf(stderr,
|
|
" -d : Enable debug output\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
static bool check_hdrfile(const char *hdrfile)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nhdrfiles; i++)
|
|
{
|
|
if (strcmp(g_hdrfiles[i], hdrfile) == 0)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static void add_hdrfile(const char *hdrfile)
|
|
{
|
|
if (hdrfile && strlen(hdrfile) > 0)
|
|
{
|
|
if (!check_hdrfile(hdrfile))
|
|
{
|
|
if (nhdrfiles > MAX_HEADER_FILES)
|
|
{
|
|
fprintf(stderr,
|
|
"ERROR: Too man header files. Increase MAX_HEADER_FILES\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
g_hdrfiles[nhdrfiles] = strdup(hdrfile);
|
|
nhdrfiles++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
int main(int argc, char **argv, char **envp)
|
|
{
|
|
char *csvpath;
|
|
char *sympath;
|
|
char *symtab;
|
|
char *nsymbols;
|
|
char *nextterm;
|
|
char *finalterm;
|
|
char *ptr;
|
|
bool cond;
|
|
FILE *instream;
|
|
FILE *outstream;
|
|
int ch;
|
|
int i;
|
|
|
|
/* Parse command line options */
|
|
|
|
symtab = SYMTAB_NAME;
|
|
nsymbols = NSYMBOLS_NAME;
|
|
g_debug = false;
|
|
|
|
while ((ch = getopt(argc, argv, ":d")) > 0)
|
|
{
|
|
switch (ch)
|
|
{
|
|
case 'd' :
|
|
g_debug = true;
|
|
break;
|
|
|
|
case '?' :
|
|
fprintf(stderr, "Unrecognized option: %c\n", optopt);
|
|
show_usage(argv[0]);
|
|
|
|
case ':' :
|
|
fprintf(stderr, "Missing option argument, option: %c\n", optopt);
|
|
show_usage(argv[0]);
|
|
|
|
default:
|
|
fprintf(stderr, "Unexpected option: %c\n", ch);
|
|
show_usage(argv[0]);
|
|
}
|
|
}
|
|
|
|
if (optind >= argc)
|
|
{
|
|
fprintf(stderr, "Missing <cvs-file> and <symtab-file>\n");
|
|
show_usage(argv[0]);
|
|
}
|
|
|
|
csvpath = argv[optind];
|
|
optind++;
|
|
|
|
if (optind >= argc)
|
|
{
|
|
fprintf(stderr, "Missing <symtab-file>\n");
|
|
show_usage(argv[0]);
|
|
}
|
|
|
|
sympath = argv[optind];
|
|
optind++;
|
|
|
|
if (optind < argc)
|
|
{
|
|
symtab = argv[optind];
|
|
optind++;
|
|
}
|
|
|
|
if (optind < argc)
|
|
{
|
|
nsymbols = argv[optind];
|
|
optind++;
|
|
}
|
|
|
|
if (optind < argc)
|
|
{
|
|
fprintf(stderr, "Unexpected garbage at the end of the line\n");
|
|
show_usage(argv[0]);
|
|
}
|
|
|
|
/* Open the CSV file for reading */
|
|
|
|
instream = fopen(csvpath, "r");
|
|
if (!instream)
|
|
{
|
|
fprintf(stderr, "open %s failed: %s\n", csvpath, strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Open the Symbol table file for writing */
|
|
|
|
outstream = fopen(sympath, "w");
|
|
if (!outstream)
|
|
{
|
|
fprintf(stderr, "open %s failed: %s\n", csvpath, strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Get all of the header files that we need to include */
|
|
|
|
while ((ptr = read_line(instream)) != NULL)
|
|
{
|
|
/* Parse the line from the CVS file */
|
|
|
|
int nargs = parse_csvline(ptr);
|
|
if (nargs < PARM1_INDEX)
|
|
{
|
|
fprintf(stderr, "Only %d arguments found: %s\n", nargs, g_line);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Add the header file to the list of header files we need to include */
|
|
|
|
add_hdrfile(g_parm[HEADER_INDEX]);
|
|
}
|
|
|
|
/* Back to the beginning */
|
|
|
|
rewind(instream);
|
|
|
|
/* Output up-front file boilerplate */
|
|
|
|
fprintf(outstream,
|
|
"/* %s: Auto-generated symbol table. Do not edit */\n\n", sympath);
|
|
fprintf(outstream, "#include <nuttx/config.h>\n");
|
|
fprintf(outstream, "#include <nuttx/compiler.h>\n");
|
|
fprintf(outstream, "#include <nuttx/symtab.h>\n\n");
|
|
|
|
/* Output all of the require header files */
|
|
|
|
for (i = 0; i < nhdrfiles; i++)
|
|
{
|
|
fprintf(outstream, "#include <%s>\n", g_hdrfiles[i]);
|
|
}
|
|
|
|
/* Now the symbol table itself */
|
|
|
|
fprintf(outstream, "\nconst struct symtab_s %s[] =\n", symtab);
|
|
fprintf(outstream, "{\n");
|
|
|
|
/* Parse each line in the CVS file */
|
|
|
|
nextterm = "";
|
|
finalterm = "";
|
|
|
|
while ((ptr = read_line(instream)) != NULL)
|
|
{
|
|
/* Parse the line from the CVS file */
|
|
|
|
int nargs = parse_csvline(ptr);
|
|
if (nargs < PARM1_INDEX)
|
|
{
|
|
fprintf(stderr, "Only %d arguments found: %s\n", nargs, g_line);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Output any conditional compilation */
|
|
|
|
cond = (g_parm[COND_INDEX] && strlen(g_parm[COND_INDEX]) > 0);
|
|
if (cond)
|
|
{
|
|
fprintf(outstream, "%s#if %s\n", nextterm, g_parm[COND_INDEX]);
|
|
nextterm = "";
|
|
}
|
|
|
|
/* Output the symbol table entry */
|
|
|
|
fprintf(outstream, "%s { \"%s\", (FAR const void *)%s }",
|
|
nextterm, g_parm[NAME_INDEX], g_parm[NAME_INDEX]);
|
|
|
|
if (cond)
|
|
{
|
|
nextterm = ",\n#endif\n";
|
|
finalterm = "\n#endif\n";
|
|
}
|
|
else
|
|
{
|
|
nextterm = ",\n";
|
|
finalterm = "\n";
|
|
}
|
|
}
|
|
|
|
fprintf(outstream, "%s};\n\n", finalterm);
|
|
fprintf(outstream,
|
|
"#define NSYMBOLS (sizeof(%s) / sizeof (struct symtab_s))\n", symtab);
|
|
fprintf(outstream, "int %s = NSYMBOLS;\n", nsymbols);
|
|
|
|
/* Close the CSV and symbol table files and exit */
|
|
|
|
fclose(instream);
|
|
fclose(outstream);
|
|
return EXIT_SUCCESS;
|
|
}
|