Merge remote-tracking branch 'origin/master' into composite
This commit is contained in:
commit
918480047a
7 changed files with 901 additions and 20 deletions
|
@ -281,31 +281,39 @@ tools/cnvwindeps$(HOSTEXEEXT):
|
|||
# setting up symbolic links with 'generic' directory names to specific,
|
||||
# configured directories.
|
||||
|
||||
Make.defs:
|
||||
echo "include $(TOPDIR)$(DELIM).config" > Make.defs
|
||||
echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs
|
||||
# Make.defs:
|
||||
# $(Q) echo "No Make.defs file found, creating one"
|
||||
# $(Q) echo "include $(TOPDIR)$(DELIM).config" > Make.defs
|
||||
# $(Q) echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs
|
||||
|
||||
# tools/initialconfig$(HOSTEXEEXT):
|
||||
# $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" initialconfig$(HOSTEXEEXT)
|
||||
#
|
||||
# .config: tools/initialconfig$(HOSTEXEEXT)
|
||||
# $(Q) echo "No .config file found, creating one"
|
||||
# $(Q) tools/initialconfig$(HOSTEXEEXT)
|
||||
|
||||
# Link the arch/<arch-name>/include directory to include/arch
|
||||
|
||||
include/arch: Make.defs
|
||||
include/arch: .config
|
||||
@echo "LN: include/arch to $(ARCH_DIR)/include"
|
||||
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_DIR)/include include/arch
|
||||
|
||||
# Link the configs/<board-name>/include directory to include/arch/board
|
||||
|
||||
include/arch/board: include/arch Make.defs include/arch
|
||||
include/arch/board: include/arch
|
||||
@echo "LN: include/arch/board to $(BOARD_DIR)/include"
|
||||
$(Q) $(DIRLINK) $(BOARD_DIR)/include include/arch/board
|
||||
|
||||
# Link the configs/<board-name>/src dir to arch/<arch-name>/src/board
|
||||
|
||||
$(ARCH_SRC)/board: Make.defs
|
||||
$(ARCH_SRC)/board: .config
|
||||
@echo "LN: $(ARCH_SRC)/board to $(BOARD_DIR)/src"
|
||||
$(Q) $(DIRLINK) $(BOARD_DIR)/src $(ARCH_SRC)/board
|
||||
|
||||
# Link arch/<arch-name>/include/<chip-name> to arch/<arch-name>/include/chip
|
||||
|
||||
$(ARCH_SRC)/chip: Make.defs
|
||||
$(ARCH_SRC)/chip: .config
|
||||
ifneq ($(CONFIG_ARCH_CHIP),)
|
||||
@echo "LN: $(ARCH_SRC)/chip to $(ARCH_SRC)/$(CONFIG_ARCH_CHIP)"
|
||||
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP) $(ARCH_SRC)/chip
|
||||
|
@ -313,7 +321,7 @@ endif
|
|||
|
||||
# Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chip
|
||||
|
||||
include/arch/chip: include/arch Make.defs
|
||||
include/arch/chip: include/arch
|
||||
ifneq ($(CONFIG_ARCH_CHIP),)
|
||||
@echo "LN: include/arch/chip to $(ARCH_INC)/$(CONFIG_ARCH_CHIP)"
|
||||
$(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP) include/arch/chip
|
||||
|
|
24
Makefile.win
24
Makefile.win
|
@ -276,13 +276,21 @@ tools\mkdeps$(HOSTEXEEXT):
|
|||
# setting up symbolic links with 'generic' directory names to specific,
|
||||
# configured directories.
|
||||
|
||||
Make.defs:
|
||||
echo "include $(TOPDIR)$(DELIM).config" > Make.defs
|
||||
echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs
|
||||
# Make.defs:
|
||||
# $(Q) echo "No Make.defs file found, creating one"
|
||||
# $(Q) echo "include $(TOPDIR)$(DELIM).config" > Make.defs
|
||||
# $(Q) echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs
|
||||
|
||||
# tools\initialconfig$(HOSTEXEEXT):
|
||||
# $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" initialconfig$(HOSTEXEEXT)
|
||||
#
|
||||
# .config: tools\initialconfig$(HOSTEXEEXT)
|
||||
# $(Q) echo "No .config file found, creating one"
|
||||
# $(Q) tools\initialconfig$(HOSTEXEEXT)
|
||||
|
||||
# Link the arch\<arch-name>\include directory to include\arch
|
||||
|
||||
include\arch: Make.defs
|
||||
include\arch: .config
|
||||
@echo LN: include\arch to $(ARCH_DIR)\include
|
||||
ifeq ($(CONFIG_WINDOWS_MKLINK),y)
|
||||
$(Q) /user:administrator mklink /d include\arch $(TOPDIR)\$(ARCH_DIR)\include
|
||||
|
@ -293,7 +301,7 @@ endif
|
|||
|
||||
# Link the configs\<board-name>\include directory to include\arch\board
|
||||
|
||||
include\arch\board: include\arch Make.defs include\arch
|
||||
include\arch\board: include\arch
|
||||
@echo LN: include\arch\board to $(BOARD_DIR)\include
|
||||
ifeq ($(CONFIG_WINDOWS_MKLINK),y)
|
||||
$(Q) /user:administrator mklink /d include\arch\board $(BOARD_DIR)\include
|
||||
|
@ -304,7 +312,7 @@ endif
|
|||
|
||||
# Link the configs\<board-name>\src dir to arch\<arch-name>\src\board
|
||||
|
||||
$(ARCH_SRC)\board: Make.defs
|
||||
$(ARCH_SRC)\board: .config
|
||||
@echo LN: $(ARCH_SRC)\board to $(BOARD_DIR)\src
|
||||
ifeq ($(CONFIG_WINDOWS_MKLINK),y)
|
||||
$(Q) /user:administrator mklink /d $(ARCH_SRC)\board $(BOARD_DIR)\src
|
||||
|
@ -315,7 +323,7 @@ endif
|
|||
|
||||
# Link arch\<arch-name>\include\<chip-name> to arch\<arch-name>\include\chip
|
||||
|
||||
$(ARCH_SRC)\chip: Make.defs
|
||||
$(ARCH_SRC)\chip: .config
|
||||
ifneq ($(CONFIG_ARCH_CHIP),)
|
||||
@echo LN: $(ARCH_SRC)\chip to $(ARCH_SRC)\$(CONFIG_ARCH_CHIP)
|
||||
ifeq ($(CONFIG_WINDOWS_MKLINK),y)
|
||||
|
@ -328,7 +336,7 @@ endif
|
|||
|
||||
# Link arch\<arch-name>\src\<chip-name> to arch\<arch-name>\src\chip
|
||||
|
||||
include\arch\chip: include\arch Make.defs
|
||||
include\arch\chip: include\arch
|
||||
ifneq ($(CONFIG_ARCH_CHIP),)
|
||||
@echo LN: include\arch\chip to $(ARCH_INC)\$(CONFIG_ARCH_CHIP)
|
||||
ifeq ($(CONFIG_WINDOWS_MKLINK),y)
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
//***************************************************************************
|
||||
|
||||
#ifndef __LIBXX_LIBXX_HXX
|
||||
#define __LIBXX_LIBXX__HXX
|
||||
#define __LIBXX_LIBXX_HXX 1
|
||||
|
||||
//***************************************************************************
|
||||
// Included Files
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# Makefile.host
|
||||
#
|
||||
# Copyright (C) 2007, 2008, 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2007, 2008, 2011-2012, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -70,7 +70,7 @@ endif
|
|||
all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \
|
||||
configure$(HOSTEXEEXT) mkconfig$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \
|
||||
mksymtab$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkversion$(HOSTEXEEXT) \
|
||||
cnvwindeps$(HOSTEXEEXT) nxstyle$(HOSTEXEEXT)
|
||||
cnvwindeps$(HOSTEXEEXT) nxstyle$(HOSTEXEEXT) initialconfig$(HOSTEXEEXT)
|
||||
default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \
|
||||
cnvwindeps$(HOSTEXEEXT)
|
||||
|
||||
|
@ -171,6 +171,17 @@ ifdef HOSTEXEEXT
|
|||
nxstyle: nxstyle$(HOSTEXEEXT)
|
||||
endif
|
||||
|
||||
# initialconfig - Create a barebones .config file sufficient only for
|
||||
# instantiating the symbolic links necesary to do a real configuration
|
||||
# from scratch.
|
||||
|
||||
initialconfig$(HOSTEXEEXT): initialconfig.c
|
||||
$(Q) $(HOSTCC) $(HOSTCFLAGS) -o initialconfig$(HOSTEXEEXT) initialconfig.c
|
||||
|
||||
ifdef HOSTEXEEXT
|
||||
initialconfig: initialconfig$(HOSTEXEEXT)
|
||||
endif
|
||||
|
||||
# cnvwindeps - Convert dependences generated by a Windows native toolchain
|
||||
# for use in a Cygwin/POSIX build environment
|
||||
|
||||
|
|
|
@ -82,6 +82,15 @@ cmdconfig.c
|
|||
This C file can be used to build a utility for comparing two NuttX
|
||||
configuration files.
|
||||
|
||||
initialconfig.c
|
||||
---------------
|
||||
|
||||
This is a C file that can be used create an initial configuration.
|
||||
This permits creating a new configuration from scratch, without
|
||||
relying on any existing board configuration in place. This utility
|
||||
will create a barebones .config file sufficient only for
|
||||
instantiating the symbolic links necesary to do a real configuration.
|
||||
|
||||
kconfig2html.c
|
||||
--------------
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ void parse_file(FILE *stream, struct variable_s **list)
|
|||
|
||||
parse_line(ptr, &varname, &varval);
|
||||
|
||||
/* If the variable has not value (or the special value 'n'), then
|
||||
/* If the variable has no value (or the special value 'n'), then
|
||||
* ignore it.
|
||||
*/
|
||||
|
||||
|
|
845
tools/initialconfig.c
Normal file
845
tools/initialconfig.c
Normal file
|
@ -0,0 +1,845 @@
|
|||
/****************************************************************************
|
||||
* tools/initialconfig.c
|
||||
*
|
||||
* Copyright (C) 2017 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 <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define MAX_LINE 512
|
||||
#define MAX_ARCHITECTURES 32
|
||||
#define MAX_MCUS 64
|
||||
#define MAX_BOARDS 128
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef int (*direntcb_t)(const char *dirpath, struct dirent *entry, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_WINDOWS_NATIVE
|
||||
static char g_delim = '\\'; /* Delimiter to use when forming paths */
|
||||
#else
|
||||
static char g_delim = '/'; /* Delimiter to use when forming paths */
|
||||
#endif
|
||||
|
||||
static const char g_archdir[] = "arch"; /* Architecture directory */
|
||||
static const char g_configdir[] = "configs"; /* Board configuration directory */
|
||||
|
||||
static char *g_arch[MAX_ARCHITECTURES]; /* List of architecture names */
|
||||
static int g_narch; /* Number of architecture names */
|
||||
static char *g_selected_arch; /* Selected architecture name */
|
||||
static char *g_selected_family; /* Selected architecture family name */
|
||||
|
||||
static char *g_mcu[MAX_MCUS]; /* List of MCU names */
|
||||
static int g_nmcu; /* Number of MCU names */
|
||||
static char *g_selected_mcu; /* Selected MCU name */
|
||||
|
||||
static char *g_board[MAX_BOARDS]; /* List of board names */
|
||||
static int g_nboard; /* Number of board names */
|
||||
static char *g_selected_board; /* Selected board name */
|
||||
|
||||
static char g_line[MAX_LINE + 1]; /* Line read from config file */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: skip_space
|
||||
*
|
||||
* Description:
|
||||
* Skip over any spaces
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char *skip_space(char *ptr)
|
||||
{
|
||||
while (*ptr && isspace((int)*ptr)) ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: find_name_end
|
||||
*
|
||||
* Description:
|
||||
* Find the end of a variable string
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char *find_name_end(char *ptr)
|
||||
{
|
||||
while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: find_value_end
|
||||
*
|
||||
* Description:
|
||||
* Find the end of a value string
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char *find_value_end(char *ptr)
|
||||
{
|
||||
while (*ptr && !isspace((int)*ptr))
|
||||
{
|
||||
if (*ptr == '"')
|
||||
{
|
||||
do ptr++; while (*ptr && *ptr != '"');
|
||||
if (*ptr) ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_line
|
||||
*
|
||||
* Description:
|
||||
* Read the next line from the configuration file
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char *read_line(FILE *stream)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
g_line[MAX_LINE] = '\0';
|
||||
if (!fgets(g_line, MAX_LINE, stream))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = skip_space(g_line);
|
||||
if (*ptr && *ptr != '#' && *ptr != '\n')
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: parse_line
|
||||
*
|
||||
* Description:
|
||||
* Parse the line from the configuration file into a variable name
|
||||
* string and a value string.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void parse_line(char *ptr, char **varname, char **varval)
|
||||
{
|
||||
/* Skip over any leading spaces */
|
||||
|
||||
ptr = skip_space(ptr);
|
||||
|
||||
/* The first no-space is the beginning of the variable name */
|
||||
|
||||
*varname = skip_space(ptr);
|
||||
*varval = NULL;
|
||||
|
||||
/* Parse to the end of the variable name */
|
||||
|
||||
ptr = find_name_end(ptr);
|
||||
|
||||
/* An equal sign is expected next, perhaps after some white space */
|
||||
|
||||
if (*ptr && *ptr != '=')
|
||||
{
|
||||
/* Some else follows the variable name. Terminate the variable
|
||||
* name and skip over any spaces.
|
||||
*/
|
||||
|
||||
*ptr = '\0';
|
||||
ptr = skip_space(ptr + 1);
|
||||
}
|
||||
|
||||
/* Verify that the equal sign is present */
|
||||
|
||||
if (*ptr == '=')
|
||||
{
|
||||
/* Make sure that the variable name is terminated (this was already
|
||||
* done if the name was followed by white space.
|
||||
*/
|
||||
|
||||
*ptr = '\0';
|
||||
|
||||
/* The variable value should follow =, perhaps separated by some
|
||||
* white space.
|
||||
*/
|
||||
|
||||
ptr = skip_space(ptr + 1);
|
||||
if (*ptr)
|
||||
{
|
||||
/* Yes.. a variable follows. Save the pointer to the start
|
||||
* of the variable string.
|
||||
*/
|
||||
|
||||
*varval = ptr;
|
||||
|
||||
/* Find the end of the variable string and make sure that it
|
||||
* is terminated.
|
||||
*/
|
||||
|
||||
ptr = find_value_end(ptr);
|
||||
*ptr = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: find_variable
|
||||
*
|
||||
* Description:
|
||||
* Return true if the selected variable exists. Also return the value of
|
||||
* the variable.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool find_variable(const char *configpath, const char *varname,
|
||||
char **varvalue)
|
||||
{
|
||||
FILE *stream;
|
||||
char *tmpname;
|
||||
char *tmpvalue;
|
||||
char *ptr;
|
||||
|
||||
stream = fopen(configpath, "r");
|
||||
if (!stream)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to open %s for reading: %s\n",
|
||||
configpath, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Loop until the entire file has been parsed. */
|
||||
|
||||
do
|
||||
{
|
||||
/* Read the next line from the file */
|
||||
|
||||
ptr = read_line(stream);
|
||||
if (ptr)
|
||||
{
|
||||
/* Parse the line into a variable and a value field */
|
||||
|
||||
tmpname = NULL;
|
||||
tmpvalue = NULL;
|
||||
parse_line(ptr, &tmpname, &tmpvalue);
|
||||
|
||||
/* Make sure that both a variable name and value name were found. */
|
||||
|
||||
if (tmpname == NULL || tmpvalue == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if this the variable name and value we are looking for */
|
||||
|
||||
if (strcmp(varname, tmpname) == 0)
|
||||
{
|
||||
/* Yes.. return the value of the variable */
|
||||
|
||||
*varvalue = tmpvalue;
|
||||
fclose(stream);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (ptr);
|
||||
|
||||
/* Return failure */
|
||||
|
||||
fclose(stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: check_variable
|
||||
*
|
||||
* Description:
|
||||
* Return true if the selected variable exists in the configuration file
|
||||
* and has the specified value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool check_variable(const char *configpath, const char *varname,
|
||||
const char *varvalue)
|
||||
{
|
||||
char *tmpvalue;
|
||||
|
||||
if (find_variable(configpath, varname, &tmpvalue))
|
||||
{
|
||||
/* The variable name exists. Does it have a value? Does the value
|
||||
* match varvalue?
|
||||
*/
|
||||
|
||||
if (tmpvalue != NULL && strcmp(varvalue, tmpvalue) == 0)
|
||||
{
|
||||
/* Yes.. return success */
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return failure */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: test_filepath
|
||||
*
|
||||
* Description:
|
||||
* Test if a regular file exists at this path.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool test_filepath(const char *filepath)
|
||||
{
|
||||
struct stat statbuf;
|
||||
int ret;
|
||||
|
||||
ret = stat(filepath, &statbuf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return S_ISREG(statbuf.st_mode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: test_dirpath
|
||||
*
|
||||
* Description:
|
||||
* Test if a regular file exists at this path.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool test_dirpath(const char *filepath)
|
||||
{
|
||||
struct stat statbuf;
|
||||
int ret;
|
||||
|
||||
ret = stat(filepath, &statbuf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return S_ISDIR(statbuf.st_mode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foreach_dirent
|
||||
*
|
||||
* Description:
|
||||
* Given a directory path, call the provided function for each entry in
|
||||
* the directory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int foreach_dirent(const char *dirpath, direntcb_t cb, void *arg)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *result;
|
||||
struct dirent entry;
|
||||
int ret;
|
||||
|
||||
dirp = opendir(dirpath);
|
||||
if (dirp == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to open directory '%s': %s\n",
|
||||
dirpath, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ret = readdir_r(dirp, &entry, &result);
|
||||
if (ret != 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Failed to reed directory '%s' entry: %s\n",
|
||||
dirpath, strerror(ret));
|
||||
closedir(dirp);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip over the . and .. hard links */
|
||||
|
||||
if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = cb(dirpath, &entry, arg);
|
||||
if (ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: enum_architectures
|
||||
*
|
||||
* Description:
|
||||
* Enumerate all architecture directory names.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int enum_architectures(const char *dirpath, struct dirent *entry, void *arg)
|
||||
{
|
||||
char *archpath;
|
||||
char *testpath;
|
||||
|
||||
/* All architecture directories should contain a Kconfig file, an include/
|
||||
* directory, and a src/ directory.
|
||||
*/
|
||||
|
||||
asprintf(&archpath, "%s%c%s", dirpath, g_delim, entry->d_name);
|
||||
asprintf(&testpath, "%s%cKconfig", archpath, g_delim);
|
||||
if (test_filepath(testpath))
|
||||
{
|
||||
free(testpath);
|
||||
asprintf(&testpath, "%s%cinclude", archpath, g_delim);
|
||||
if (test_dirpath(testpath))
|
||||
{
|
||||
free(testpath);
|
||||
asprintf(&testpath, "%s%csrc", archpath, g_delim);
|
||||
if (test_dirpath(testpath))
|
||||
{
|
||||
if (g_narch >= MAX_ARCHITECTURES)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Too many architecture directories found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_arch[g_narch] = strdup(entry->d_name);
|
||||
g_narch++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(testpath);
|
||||
free(archpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: enum_mcus
|
||||
*
|
||||
* Description:
|
||||
* Enumerate all MCU directory names.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int enum_mcus(const char *dirpath, struct dirent *entry, void *arg)
|
||||
{
|
||||
char *mcupath;
|
||||
char *testpath;
|
||||
|
||||
/* All MCU directories should contain a Kconfig and a Make.defs file. */
|
||||
|
||||
asprintf(&mcupath, "%s%c%s", dirpath, g_delim, entry->d_name);
|
||||
asprintf(&testpath, "%s%cKconfig", mcupath, g_delim);
|
||||
if (test_filepath(testpath))
|
||||
{
|
||||
free(testpath);
|
||||
asprintf(&testpath, "%s%cMake.defs", mcupath, g_delim);
|
||||
if (test_filepath(testpath))
|
||||
{
|
||||
if (g_nmcu >= MAX_MCUS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Too many MCU directories found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_mcu[g_nmcu] = strdup(entry->d_name);
|
||||
g_nmcu++;
|
||||
}
|
||||
}
|
||||
|
||||
free(testpath);
|
||||
free(mcupath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: enum_board_configurations
|
||||
*
|
||||
* Description:
|
||||
* Enumerate all configurations for boards find the configuration
|
||||
* directory for the selected MCU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int enum_board_configurations(const char *dirpath,
|
||||
struct dirent *entry, void *arg)
|
||||
{
|
||||
char *configpath;
|
||||
char *varvalue;
|
||||
int ret = 0;
|
||||
|
||||
/* All board directories should contain a defconfig file. */
|
||||
|
||||
asprintf(&configpath, "%s%c%s%cdefconfig",
|
||||
dirpath, g_delim, entry->d_name, g_delim);
|
||||
if (test_filepath(configpath))
|
||||
{
|
||||
/* We don't want all board configurations, we only want the name of
|
||||
* the board that includes a configuration with:
|
||||
*
|
||||
* CONFIG_ARCH_CHIP="xxxx"
|
||||
*
|
||||
* Where xxxx is the selected MCU name.
|
||||
*/
|
||||
|
||||
asprintf(&varvalue, "\"%s\"", g_selected_mcu);
|
||||
if (check_variable(configpath, "CONFIG_ARCH_CHIP", varvalue))
|
||||
{
|
||||
/* Found it... add the board name to the list of boards for the
|
||||
* selected MCU.
|
||||
*/
|
||||
|
||||
if (g_nboard >= MAX_BOARDS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Too many board configurations found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g_board[g_nboard] = strdup(arg);
|
||||
g_nboard++;
|
||||
|
||||
/* If we have not yet extracted the architecture family, then do
|
||||
* that here.
|
||||
*/
|
||||
|
||||
if (g_selected_family == NULL)
|
||||
{
|
||||
char *family;
|
||||
|
||||
if (find_variable(configpath, "CONFIG_ARCH_FAMILY", &family))
|
||||
{
|
||||
g_selected_family = strdup(family);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop the enumeration if we find a match. Continue if not...
|
||||
* that is because one board might possible support multiple
|
||||
* architectures.
|
||||
*/
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
free(varvalue);
|
||||
}
|
||||
|
||||
free(configpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: enum_boards
|
||||
*
|
||||
* Description:
|
||||
* Enumerate all boards find the configuration directory for the selected
|
||||
* MCU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int enum_boards(const char *dirpath, struct dirent *entry, void *arg)
|
||||
{
|
||||
char *boardpath;
|
||||
char *testpath;
|
||||
|
||||
/* All board directories should contain a Kconfig file, an include/
|
||||
* directory, and a src/ directory.
|
||||
*/
|
||||
|
||||
asprintf(&boardpath, "%s%c%s", dirpath, g_delim, entry->d_name);
|
||||
asprintf(&testpath, "%s%cKconfig", boardpath, g_delim);
|
||||
if (test_filepath(testpath))
|
||||
{
|
||||
free(testpath);
|
||||
asprintf(&testpath, "%s%cinclude", boardpath, g_delim);
|
||||
if (test_dirpath(testpath))
|
||||
{
|
||||
free(testpath);
|
||||
asprintf(&testpath, "%s%csrc", boardpath, g_delim);
|
||||
if (test_dirpath(testpath))
|
||||
{
|
||||
/* Enumerate the board configurations */
|
||||
|
||||
(void)foreach_dirent(boardpath, enum_board_configurations,
|
||||
entry->d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(testpath);
|
||||
free(boardpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: list_select
|
||||
*
|
||||
* Description:
|
||||
* Select one value from a list.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
char *list_select(char **list, unsigned nitems)
|
||||
{
|
||||
char ch;
|
||||
int ndx;
|
||||
int i;
|
||||
|
||||
/* Show the list */
|
||||
|
||||
for (i = 0, ch = '1'; i < nitems; i++)
|
||||
{
|
||||
printf(" %c. %s\n", ch, list[i]);
|
||||
if (ch == '9')
|
||||
{
|
||||
ch = 'a';
|
||||
}
|
||||
else if (ch == 'z')
|
||||
{
|
||||
ch = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
for(; ; )
|
||||
{
|
||||
bool input = false;
|
||||
|
||||
printf("Enter [1");
|
||||
if (nitems > 1)
|
||||
{
|
||||
printf("-%c", nitems >= 9 ? '9' : '0' + nitems);
|
||||
if (nitems > 9)
|
||||
{
|
||||
printf(",a");
|
||||
if (nitems > 10)
|
||||
{
|
||||
printf("-%c", 'a' + nitems - 10);
|
||||
if (nitems > 35)
|
||||
{
|
||||
printf(",A");
|
||||
if (nitems > 36)
|
||||
{
|
||||
printf("-%c", 'A' + nitems - 36);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("]: ");
|
||||
|
||||
do
|
||||
{
|
||||
ch = getchar();
|
||||
if (ch >= '1' && ch <= '9')
|
||||
{
|
||||
ndx = ch - '1';
|
||||
}
|
||||
else if (ch >= 'a' && ch <= 'z')
|
||||
{
|
||||
ndx = ch - 'a' + 9;
|
||||
}
|
||||
else if (ch >= 'A' && ch <= 'Z')
|
||||
{
|
||||
ndx = ch - 'A' + 35;
|
||||
}
|
||||
else if (ch == '\n')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid selection: %c -- Try again\n", ch);
|
||||
input = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ndx < nitems)
|
||||
{
|
||||
return list[ndx];
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid selection: %c -- Try again\n", ch);
|
||||
input = true;
|
||||
}
|
||||
}
|
||||
while (!input);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: create_config
|
||||
*
|
||||
* Description:
|
||||
* Generate a bogus .config file. There is only sufficient information
|
||||
* in this bogus .config to estable the correct symbolic links.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void create_config(void)
|
||||
{
|
||||
FILE *stream;
|
||||
|
||||
stream = fopen(".config", "w");
|
||||
if (!stream)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to open .config for writing: %s\n",
|
||||
strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fprintf(stream, "CONFIG_ARCH=\"%s\"\n", g_selected_arch);
|
||||
if (g_selected_family != NULL)
|
||||
{
|
||||
fprintf(stream, "CONFIG_ARCH_FAMILY=%s\n", g_selected_family);
|
||||
}
|
||||
|
||||
fprintf(stream, "CONFIG_ARCH_CHIP=\"%s\"\n", g_selected_mcu);
|
||||
fprintf(stream, "CONFIG_ARCH_BOARD=\"%s\"\n", g_selected_board);
|
||||
|
||||
fclose(stream);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: main
|
||||
*
|
||||
* Description:
|
||||
* Program entry point.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *archpath;
|
||||
|
||||
/* Enumerate all of the architectures */
|
||||
|
||||
g_narch = 0;
|
||||
foreach_dirent(g_archdir, enum_architectures, NULL);
|
||||
|
||||
/* Select an architecture */
|
||||
|
||||
printf("Select an architecture:\n");
|
||||
g_selected_arch = list_select(g_arch, g_narch);
|
||||
|
||||
/* Enumerate the MCUs for the selected architecture */
|
||||
|
||||
g_nmcu = 0;
|
||||
asprintf(&archpath, "%s%c%s%csrc", g_archdir, g_delim, g_selected_arch, g_delim);
|
||||
foreach_dirent(archpath, enum_mcus, NULL);
|
||||
|
||||
/* Select an MCU */
|
||||
|
||||
printf("Select an MCU for architecture=%s:\n", g_selected_arch);
|
||||
g_selected_mcu = list_select(g_mcu, g_nmcu);
|
||||
|
||||
/* Enumerate the boards for the selected MCU */
|
||||
|
||||
g_nboard = 0;
|
||||
foreach_dirent(g_configdir, enum_boards, NULL);
|
||||
|
||||
/* Select an board */
|
||||
|
||||
printf("Select a board for MCU=%s:\n", g_selected_mcu);
|
||||
g_selected_board = list_select(g_board, g_nboard);
|
||||
|
||||
/* Then output a bogus .config file with enough information to establish
|
||||
* the correct symbolic links
|
||||
*/
|
||||
|
||||
create_config();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue