331 lines
8.5 KiB
C
331 lines
8.5 KiB
C
/****************************************************************************
|
|
* tools/mksymtab.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* 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;
|
|
bool parm1;
|
|
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 */
|
|
|
|
g_parm[NAME_INDEX][0] = 0;
|
|
g_parm[HEADER_INDEX][0] = 0;
|
|
g_parm[COND_INDEX][0] = 0;
|
|
g_parm[RETTYPE_INDEX][0] = 0;
|
|
g_parm[PARM1_INDEX][0] = 0;
|
|
|
|
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 = 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 */
|
|
|
|
parm1 = strlen(g_parm[PARM1_INDEX]) > 0;
|
|
if (parm1)
|
|
{
|
|
fprintf(outstream, "%s { \"%s\", (FAR const void *)%s }",
|
|
nextterm, g_parm[NAME_INDEX], g_parm[NAME_INDEX]);
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|