various menuselect fixes as a result of boredom during a 9 hour flight and
now a 9 hour layover ... - If a module is disabled from being built because of failed dependencies or a conflict, automatically re-enable the module if the issues are later resolved. - If a module has been disabled by default, only set this value if there is not an existing menuselect.makeopts file. Previously, this value would get reset every time you ran menuselect. - staticize a bunch of functions and variables that aren't public git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@25287 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
e080c242f1
commit
7abda7787e
|
@ -72,46 +72,34 @@ struct tree {
|
|||
};
|
||||
|
||||
/*! The list of trees from makeopts.xml files */
|
||||
AST_LIST_HEAD_NOLOCK_STATIC(trees, tree);
|
||||
static AST_LIST_HEAD_NOLOCK_STATIC(trees, tree);
|
||||
|
||||
const char * const makeopts_files[] = {
|
||||
static const char * const makeopts_files[] = {
|
||||
"makeopts.xml"
|
||||
};
|
||||
|
||||
char *output_makeopts = OUTPUT_MAKEOPTS_DEFAULT;
|
||||
static char *output_makeopts = OUTPUT_MAKEOPTS_DEFAULT;
|
||||
|
||||
/*! This is set to 1 if menuselect.makeopts pre-existed the execution of this app */
|
||||
int existing_config = 0;
|
||||
static int existing_config = 0;
|
||||
|
||||
/*! This is set when the --check-deps argument is provided. */
|
||||
int check_deps = 0;
|
||||
static int check_deps = 0;
|
||||
|
||||
/*! Force a clean of the source tree */
|
||||
int force_clean = 0;
|
||||
static int force_clean = 0;
|
||||
|
||||
int add_category(struct category *cat);
|
||||
int add_member(struct member *mem, struct category *cat);
|
||||
int parse_makeopts_xml(const char *makeopts_xml);
|
||||
int process_deps(void);
|
||||
int build_member_list(void);
|
||||
void mark_as_present(const char *member, const char *category);
|
||||
int parse_existing_config(const char *infile);
|
||||
int generate_makeopts_file(void);
|
||||
void free_member_list(void);
|
||||
void free_trees(void);
|
||||
|
||||
/*! \brief a wrapper for calloc() that generates an error message if the allocation fails */
|
||||
static inline void *my_calloc(size_t num, size_t len)
|
||||
{
|
||||
void *tmp;
|
||||
|
||||
tmp = calloc(num, len);
|
||||
|
||||
if (!tmp)
|
||||
fprintf(stderr, "Memory allocation error!\n");
|
||||
|
||||
return tmp;
|
||||
}
|
||||
static int add_category(struct category *cat);
|
||||
static int add_member(struct member *mem, struct category *cat);
|
||||
static int parse_makeopts_xml(const char *makeopts_xml);
|
||||
static int process_deps(void);
|
||||
static int build_member_list(void);
|
||||
static void mark_as_present(const char *member, const char *category);
|
||||
static void process_prev_failed_deps(char *buf);
|
||||
static int parse_existing_config(const char *infile);
|
||||
static int generate_makeopts_file(void);
|
||||
static void free_member_list(void);
|
||||
static void free_trees(void);
|
||||
|
||||
/*! \brief return a pointer to the first non-whitespace character */
|
||||
static inline char *skip_blanks(char *str)
|
||||
|
@ -126,7 +114,7 @@ static inline char *skip_blanks(char *str)
|
|||
}
|
||||
|
||||
/*! \brief Add a category to the category list, ensuring that there are no duplicates */
|
||||
int add_category(struct category *cat)
|
||||
static int add_category(struct category *cat)
|
||||
{
|
||||
struct category *tmp;
|
||||
|
||||
|
@ -142,7 +130,7 @@ int add_category(struct category *cat)
|
|||
}
|
||||
|
||||
/*! \brief Add a member to the member list of a category, ensuring that there are no duplicates */
|
||||
int add_member(struct member *mem, struct category *cat)
|
||||
static int add_member(struct member *mem, struct category *cat)
|
||||
{
|
||||
struct member *tmp;
|
||||
|
||||
|
@ -158,7 +146,7 @@ int add_member(struct member *mem, struct category *cat)
|
|||
}
|
||||
|
||||
/*! \brief Parse an input makeopts file */
|
||||
int parse_makeopts_xml(const char *makeopts_xml)
|
||||
static int parse_makeopts_xml(const char *makeopts_xml)
|
||||
{
|
||||
FILE *f;
|
||||
struct category *cat;
|
||||
|
@ -177,7 +165,7 @@ int parse_makeopts_xml(const char *makeopts_xml)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!(tree = my_calloc(1, sizeof(*tree)))) {
|
||||
if (!(tree = calloc(1, sizeof(*tree)))) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
@ -195,7 +183,7 @@ int parse_makeopts_xml(const char *makeopts_xml)
|
|||
cur;
|
||||
cur = mxmlFindElement(cur, menu, "category", NULL, NULL, MXML_DESCEND))
|
||||
{
|
||||
if (!(cat = my_calloc(1, sizeof(*cat))))
|
||||
if (!(cat = calloc(1, sizeof(*cat))))
|
||||
return -1;
|
||||
|
||||
cat->name = mxmlElementGetAttr(cur, "name");
|
||||
|
@ -214,29 +202,23 @@ int parse_makeopts_xml(const char *makeopts_xml)
|
|||
cur2;
|
||||
cur2 = mxmlFindElement(cur2, cur, "member", NULL, NULL, MXML_DESCEND))
|
||||
{
|
||||
if (!(mem = my_calloc(1, sizeof(*mem))))
|
||||
if (!(mem = calloc(1, sizeof(*mem))))
|
||||
return -1;
|
||||
|
||||
if (!cat->positive_output)
|
||||
mem->enabled = 1; /* Enabled by default */
|
||||
|
||||
mem->name = mxmlElementGetAttr(cur2, "name");
|
||||
|
||||
|
||||
if (!cat->positive_output)
|
||||
mem->enabled = 1;
|
||||
|
||||
cur3 = mxmlFindElement(cur2, cur2, "defaultenabled", NULL, NULL, MXML_DESCEND);
|
||||
if (cur3 && cur3->child) {
|
||||
if (!strcasecmp("no", cur3->child->value.opaque))
|
||||
mem->enabled = 0;
|
||||
else if (!strcasecmp("yes", cur3->child->value.opaque))
|
||||
mem->enabled = 1;
|
||||
else
|
||||
fprintf(stderr, "Invalid value '%s' for <defaultenabled> !\n", cur3->child->value.opaque);
|
||||
}
|
||||
if (cur3 && cur3->child)
|
||||
mem->defaultenabled = cur3->child->value.opaque;
|
||||
|
||||
for (cur3 = mxmlFindElement(cur2, cur2, "depend", NULL, NULL, MXML_DESCEND);
|
||||
cur3 && cur3->child;
|
||||
cur3 = mxmlFindElement(cur3, cur2, "depend", NULL, NULL, MXML_DESCEND))
|
||||
{
|
||||
if (!(dep = my_calloc(1, sizeof(*dep))))
|
||||
if (!(dep = calloc(1, sizeof(*dep))))
|
||||
return -1;
|
||||
if (!strlen_zero(cur3->child->value.opaque)) {
|
||||
dep->name = cur3->child->value.opaque;
|
||||
|
@ -249,7 +231,7 @@ int parse_makeopts_xml(const char *makeopts_xml)
|
|||
cur3 && cur3->child;
|
||||
cur3 = mxmlFindElement(cur3, cur2, "conflict", NULL, NULL, MXML_DESCEND))
|
||||
{
|
||||
if (!(cnf = my_calloc(1, sizeof(*cnf))))
|
||||
if (!(cnf = calloc(1, sizeof(*cnf))))
|
||||
return -1;
|
||||
if (!strlen_zero(cur3->child->value.opaque)) {
|
||||
cnf->name = cur3->child->value.opaque;
|
||||
|
@ -269,7 +251,7 @@ int parse_makeopts_xml(const char *makeopts_xml)
|
|||
}
|
||||
|
||||
/*! \brief Process dependencies against the input dependencies file */
|
||||
int process_deps(void)
|
||||
static int process_deps(void)
|
||||
{
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
@ -297,7 +279,7 @@ int process_deps(void)
|
|||
strsep(&p, "=");
|
||||
if (!p)
|
||||
continue;
|
||||
if (!(dep_file = my_calloc(1, sizeof(*dep_file))))
|
||||
if (!(dep_file = calloc(1, sizeof(*dep_file))))
|
||||
break;
|
||||
strncpy(dep_file->name, buf, sizeof(dep_file->name) - 1);
|
||||
dep_file->met = atoi(p);
|
||||
|
@ -321,20 +303,6 @@ int process_deps(void)
|
|||
if (mem->depsfailed)
|
||||
break; /* This dependency is not met, so we can stop now */
|
||||
}
|
||||
if (mem->depsfailed) {
|
||||
if (check_deps && existing_config && mem->enabled) {
|
||||
/* Config already existed, but this module was not disabled.
|
||||
* However, according to our current list of dependencies that
|
||||
* have been met, this can not be built. */
|
||||
res = -1;
|
||||
fprintf(stderr, "\nThe existing menuselect.makeopts did not specify that %s should not be built\n", mem->name);
|
||||
fprintf(stderr, "However, menuselect-deps indicates that dependencies for this module have not\n");
|
||||
fprintf(stderr, "been met. So, either remove the existing menuselect.makeopts file, or run\n");
|
||||
fprintf(stderr, "'make menuselect' to generate a file that is correct.\n\n");
|
||||
goto deps_file_free;
|
||||
}
|
||||
mem->enabled = 0; /* Automatically disable it if dependencies not met */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,25 +321,9 @@ int process_deps(void)
|
|||
if (mem->conflictsfailed)
|
||||
break; /* This conflict was found, so we can stop now */
|
||||
}
|
||||
if (mem->conflictsfailed) {
|
||||
if (check_deps && existing_config && mem->enabled) {
|
||||
/* Config already existed, but this module was not disabled.
|
||||
* However, according to our current list of conflicts that
|
||||
* exist, this can not be built. */
|
||||
res = -1;
|
||||
fprintf(stderr, "\nThe existing menuselect.makeopts did not specify that %s should not be built\n", mem->name);
|
||||
fprintf(stderr, "However, menuselect-deps indicates that conflicts for this module exist.\n");
|
||||
fprintf(stderr, "So, either remove the existing menuselect.makeopts file, or run\n");
|
||||
fprintf(stderr, "'make menuselect' to generate a file that is correct.\n\n");
|
||||
goto deps_file_free;
|
||||
}
|
||||
mem->enabled = 0; /* Automatically disable it if conflicts exist */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deps_file_free:
|
||||
|
||||
/* Free the dependency list we built from the file */
|
||||
while ((dep_file = AST_LIST_REMOVE_HEAD(&deps_file, list)))
|
||||
free(dep_file);
|
||||
|
@ -380,7 +332,7 @@ deps_file_free:
|
|||
}
|
||||
|
||||
/*! \brief Iterate through all of the input makeopts files and call the parse function on them */
|
||||
int build_member_list(void)
|
||||
static int build_member_list(void)
|
||||
{
|
||||
int i;
|
||||
int res = -1;
|
||||
|
@ -396,7 +348,7 @@ int build_member_list(void)
|
|||
}
|
||||
|
||||
/*! \brief Given the string representation of a member and category, mark it as present in a given input file */
|
||||
void mark_as_present(const char *member, const char *category)
|
||||
static void mark_as_present(const char *member, const char *category)
|
||||
{
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
@ -437,8 +389,45 @@ void toggle_enabled(struct category *cat, int index)
|
|||
}
|
||||
}
|
||||
|
||||
/*! \brief Process a previously failed dependency
|
||||
*
|
||||
* If a module was previously disabled because of a failed dependency
|
||||
* or a conflict, and not because the user selected it to be that way,
|
||||
* then it needs to be re-enabled by default if the problem is no longer present.
|
||||
*/
|
||||
static void process_prev_failed_deps(char *buf)
|
||||
{
|
||||
const char *cat_name, *mem_name;
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
||||
cat_name = strsep(&buf, "=");
|
||||
mem_name = strsep(&buf, "\n");
|
||||
|
||||
if (!cat_name || !mem_name)
|
||||
return;
|
||||
|
||||
AST_LIST_TRAVERSE(&categories, cat, list) {
|
||||
if (strcasecmp(cat->name, cat_name))
|
||||
continue;
|
||||
AST_LIST_TRAVERSE(&cat->members, mem, list) {
|
||||
if (strcasecmp(mem->name, mem_name))
|
||||
continue;
|
||||
|
||||
if (!mem->depsfailed && !mem->conflictsfailed)
|
||||
mem->enabled = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cat || !mem)
|
||||
fprintf(stderr, "Unable to find '%s' in category '%s'\n", mem_name, cat_name);
|
||||
}
|
||||
|
||||
/*! \brief Parse an existing output makeopts file and enable members previously selected */
|
||||
int parse_existing_config(const char *infile)
|
||||
static int parse_existing_config(const char *infile)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[2048];
|
||||
|
@ -474,13 +463,18 @@ int parse_existing_config(const char *infile)
|
|||
fprintf(stderr, "Invalid string in '%s' at line '%d'!\n", output_makeopts, lineno);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
parse = skip_blanks(parse);
|
||||
|
||||
if (!strcasecmp(category, "MENUSELECT_DEPSFAILED")) {
|
||||
process_prev_failed_deps(parse);
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((member = strsep(&parse, " \n"))) {
|
||||
member = skip_blanks(member);
|
||||
if (strlen_zero(member))
|
||||
continue;
|
||||
|
||||
mark_as_present(member, category);
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +485,7 @@ int parse_existing_config(const char *infile)
|
|||
}
|
||||
|
||||
/*! \brief Create the output makeopts file that results from the user's selections */
|
||||
int generate_makeopts_file(void)
|
||||
static int generate_makeopts_file(void)
|
||||
{
|
||||
FILE *f;
|
||||
struct category *cat;
|
||||
|
@ -513,6 +507,14 @@ int generate_makeopts_file(void)
|
|||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
/* Output which members were disabled because of failed dependencies or conflicts */
|
||||
AST_LIST_TRAVERSE(&categories, cat, list) {
|
||||
AST_LIST_TRAVERSE(&cat->members, mem, list) {
|
||||
if (mem->depsfailed || mem->conflictsfailed)
|
||||
fprintf(f, "MENUSELECT_DEPSFAILED=%s=%s\n", cat->name, mem->name);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
|
@ -520,7 +522,7 @@ int generate_makeopts_file(void)
|
|||
|
||||
#ifdef MENUSELECT_DEBUG
|
||||
/*! \brief Print out all of the information contained in our tree */
|
||||
void dump_member_list(void)
|
||||
static void dump_member_list(void)
|
||||
{
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
@ -545,7 +547,7 @@ void dump_member_list(void)
|
|||
#endif
|
||||
|
||||
/*! \brief Free all categories and their members */
|
||||
void free_member_list(void)
|
||||
static void free_member_list(void)
|
||||
{
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
@ -565,7 +567,7 @@ void free_member_list(void)
|
|||
}
|
||||
|
||||
/*! \brief Free all of the XML trees */
|
||||
void free_trees(void)
|
||||
static void free_trees(void)
|
||||
{
|
||||
struct tree *tree;
|
||||
|
||||
|
@ -608,6 +610,52 @@ int count_members(struct category *cat)
|
|||
return count;
|
||||
}
|
||||
|
||||
/*! \brief Make sure an existing menuselect.makeopts disabled everything it should have */
|
||||
static int sanity_check(void)
|
||||
{
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
||||
AST_LIST_TRAVERSE(&categories, cat, list) {
|
||||
AST_LIST_TRAVERSE(&cat->members, mem, list) {
|
||||
if ((mem->depsfailed || mem->conflictsfailed) && mem->enabled) {
|
||||
fprintf(stderr, "\n***********************************************************\n"
|
||||
" The existing menuselect.makeopts file did not specify \n"
|
||||
" that '%s' should not be included. However, either some \n"
|
||||
" dependencies for this module were not found or a \n"
|
||||
" conflict exists. \n"
|
||||
" \n"
|
||||
" Either run 'make menuselect' or remove the existing \n"
|
||||
" menuselect.makeopts file to resolve this issue. \n"
|
||||
"***********************************************************\n\n", mem->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* \brief Set the forced default values if they exist */
|
||||
static void process_defaults(void)
|
||||
{
|
||||
struct category *cat;
|
||||
struct member *mem;
|
||||
|
||||
AST_LIST_TRAVERSE(&categories, cat, list) {
|
||||
AST_LIST_TRAVERSE(&cat->members, mem, list) {
|
||||
if (!mem->defaultenabled)
|
||||
continue;
|
||||
|
||||
if (!strcasecmp(mem->defaultenabled, "yes"))
|
||||
mem->enabled = 1;
|
||||
else if (!strcasecmp(mem->defaultenabled, "no"))
|
||||
mem->enabled = 0;
|
||||
else
|
||||
fprintf(stderr, "Invalid defaultenabled value for '%s' in category '%s'\n", mem->name, cat->name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int res = 0;
|
||||
|
@ -616,7 +664,10 @@ int main(int argc, char *argv[])
|
|||
/* Parse the input XML files to build the list of available options */
|
||||
if ((res = build_member_list()))
|
||||
exit(res);
|
||||
|
||||
|
||||
/* Process module dependencies */
|
||||
res = process_deps();
|
||||
|
||||
/* The --check-deps option is used to ask this application to check to
|
||||
* see if that an existing menuselect.makeopts file contails all of the
|
||||
* modules that have dependencies that have not been met. If this
|
||||
|
@ -629,17 +680,20 @@ int main(int argc, char *argv[])
|
|||
res = parse_existing_config(argv[x]);
|
||||
if (!res && !strcasecmp(argv[x], OUTPUT_MAKEOPTS_DEFAULT))
|
||||
existing_config = 1;
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process module dependencies */
|
||||
res = process_deps();
|
||||
|
||||
#ifdef MENUSELECT_DEBUG
|
||||
/* Dump the list produced by parsing the various input files */
|
||||
dump_member_list();
|
||||
#endif
|
||||
|
||||
if (!existing_config)
|
||||
process_defaults();
|
||||
else if (check_deps)
|
||||
res = sanity_check();
|
||||
|
||||
/* Run the menu to let the user enable/disable options */
|
||||
if (!check_deps && !res)
|
||||
res = run_menu();
|
||||
|
@ -664,6 +718,9 @@ int main(int argc, char *argv[])
|
|||
res = -1;
|
||||
}
|
||||
|
||||
/* In some cases, such as modifying the CFLAGS for the build,
|
||||
* a "make clean" needs to be forced. Removing the .lastclean
|
||||
* file does this. */
|
||||
if (force_clean)
|
||||
unlink(".lastclean");
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief defaults for menuselect
|
||||
* \brief public data structures and defaults for menuselect
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -37,6 +37,8 @@ struct conflict;
|
|||
struct member {
|
||||
/*! What will be sent to the makeopts file */
|
||||
const char *name;
|
||||
/*! Default setting */
|
||||
const char *defaultenabled;
|
||||
/*! This module is currently selected */
|
||||
int enabled;
|
||||
/*! This module has failed dependencies */
|
||||
|
|
Loading…
Reference in New Issue