From 16c79296601ef29c7502ab21109d9fb2690a694a Mon Sep 17 00:00:00 2001 From: Keith Marshall Date: Thu, 24 Jun 2010 20:49:39 +0000 Subject: [PATCH] Include alias search, when matching component package name. --- ChangeLog | 19 ++++++++++++ src/keyword.c | 85 ++++++++++++++++++++++------------------------------ src/pkgfind.cpp | 92 +++++++++++++++++++++++++++++++++------------------------ 3 files changed, 109 insertions(+), 87 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7188614..7afb6c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2010-06-24 Keith Marshall + + Include alias search, when matching component package name. + + * src/keyword.c (has_keyword): Rearrange argument declarations for + more natural order; update all callers accordingly. Simplify; compare + keyword to be matched with each successive candidate from match-list, + character-by-character and in-place, so avoiding memory allocation + for any local duplicate of the passed match-list; thus... + (safe_strdup): ...this static function no longer required; delete it. + (string.h): No references remain; do not include it. + + * src/pkgfind.cpp (pkgXmlNode::FindPackageByName): Augment component + package name matching to include potential matches of the look-up name + with trailing component name stripped off, when that matches the class + name of an identified component package, and the initial substring of + the look-up name, after stripping, matches any specified alias name + for the containing package. + 2010-06-10 Keith Marshall Address FIXME relating to identification of distributable files. diff --git a/src/keyword.c b/src/keyword.c index 8b7c11b..a762645 100644 --- a/src/keyword.c +++ b/src/keyword.c @@ -4,11 +4,11 @@ * $Id$ * * Written by Keith Marshall - * Copyright (C) 2009, MinGW Project + * Copyright (C) 2009, 2010 MinGW Project * * * Implementation of "has_keyword()" function; this is used to check - * for the presence of a specified keyword with a wihtespace separated + * for the presence of a specified keyword with a whitespace separated * list, appearing as an XML property string. * * @@ -27,72 +27,59 @@ * */ #include -#include #include #define FALSE 0 #define TRUE !FALSE -static inline -char *safe_strdup( const char *src ) +int has_keyword( const char *lookup, const char *in_list ) { - /* Duplicate a "C" string into dynamically allocated memory, - * safely handling a NULL source reference. + /* Check if the keyword specified by "lookup" is present in + * the white-space separated list specified by "in_list". */ - return src ? strdup( src ) : NULL; -} - -int has_keyword( const char *keywords, const char *wanted ) -{ - /* Check the given "keywords" list for the presence of - * the "wanted" keyword. - */ - char *inspect; - if( (inspect = safe_strdup( keywords )) != NULL ) + if( (lookup != NULL) && (in_list != NULL) ) { - /* We've found a non-empty list of keywords to inspect; - * initialise a pointer to the first entry for matching... + /* Provided both "lookup" and "in_list" are specified... */ - char *match = inspect; - while( *match ) + while( *in_list ) { - /* We haven't yet checked all of the available keywords; - * locate the end of the current inspection reference... - */ - char *brk = match; - while( *brk && ! isspace( *brk ) ) - ++brk; - - /* ...and append a NUL terminator. + /* ...and while we haven't run out of list entries to match... + * + * Perform a character-by-character comparison between the + * "lookup" string and the leading entry in the currently + * unchecked section of "in_list"... */ - if( *brk ) - *brk++ = '\0'; + const char *inspect = lookup; + while( *inspect && ! isspace( *in_list ) && (*inspect++ == *in_list++) ) + /* + * ...advancing pointers to both, with no further action, + * until we find a mismatch. + */ + ; - /* Check the currently selected alias... + /* If the mismatch coincides with the terminating NUL for "lookup", + * AND we've simultaneously encountered a keyword separator, or the + * terminating NUL for "in_list"... */ - if( strcmp( match, wanted ) == 0 ) - { - /* ...and if it's a match, then immediately release the - * scratch-pad memory we used for the keyword comparisons, - * and return "true". + if( (*inspect == '\0') && ((*in_list == '\0') || isspace( *in_list )) ) + /* + * ...then we have found a keyword match... */ - free( (void *)(inspect) ); return TRUE; - } - /* Otherwise, proceed to check the next keyword, if any. + /* Otherwise, we have not yet found a match... + * Step over any remaining non-white-space characters in the current + * "in_list" entry, and also the following space character if any... */ - match = brk; + while( *in_list && ! isspace( *in_list++ ) ) + /* + * ...until we either exhaust "in_list", or we are ready to cycle + * back to evaluate the next potentially matching entry. + */ + ; } - - /* If we get to here, then all assigned aliases have been - * checked, without finding a match; the scratch-pad memory - * remains allocated, so release it, before falling through - * to return "false". - */ - free( (void *)(inspect) ); } - /* Return "false" in all cases where no matching name can be found. + /* If we get to here, then there was no match for "lookup" in "in_list"... */ return FALSE; } diff --git a/src/pkgfind.cpp b/src/pkgfind.cpp index 2b29983..3f7edd7 100644 --- a/src/pkgfind.cpp +++ b/src/pkgfind.cpp @@ -31,18 +31,28 @@ #include "pkgkeys.h" pkgXmlNode * -pkgXmlDocument::FindPackageByName( const char *name, const char *subsystem ) +pkgXmlDocument::FindPackageByName( const char *lookup, const char *subsystem ) { + /* Create a local copy of the package "name" which we are required to + * "lookup"; this allows us to make temporary adjustments to facilitate + * stripping of any "component" identifying suffix, which might occlude + * a match for a package "alias" name. + */ + int len; char name[ 1 + (len = strlen( lookup )) ]; + strcpy( name, lookup ); + + /* Working from the root of the package directory tree... + */ pkgXmlNode *dir = GetRoot()->GetChildren(); /* - * Working from the root of the package directory tree... * search all "package-collection" XML nodes, to locate a package * by "name"; return a pointer to the XML node which contains the * specification for the package, or NULL if no such package. */ while( dir != NULL ) { - /* Select only "package-collection" elements... + /* Select only "package-collection" elements, which have been + * assigned the desired "subsystem" property... */ if( dir->IsElementOfType( package_collection_key ) && subsystem_strcmp( subsystem, dir->GetPropVal( subsystem_key, NULL )) ) @@ -59,55 +69,61 @@ pkgXmlDocument::FindPackageByName( const char *name, const char *subsystem ) /* ...return immediately, if it has a "name" or an "alias" * property which matches the required package name... */ - if( (strcmp( name, pkg->GetPropVal( name_key, "" )) == 0) - || (has_keyword( pkg->GetPropVal( alias_key, NULL ), name ) != 0) ) + const char *pkg_name, *alias; + if( (strcmp( name, pkg_name = pkg->GetPropVal( name_key, "" )) == 0) + || (has_keyword( name, alias = pkg->GetPropVal( alias_key, NULL ) ) != 0) ) return pkg; - else + /* We did find a "package" element, but neither its "name" + * nor its "alias" property provided a match; look within it, + * for a possible match on a "component" package element... + */ + pkgXmlNode *cpt = pkg->GetChildren(); + while( cpt != NULL ) { - /* We did find a "package" element, but neither its "name" - * nor its "alias" property provided a match; look within it, - * for a possible match on a "component" package element... + /* For each element contained within the "package" definition, + * check if it represents a "component" package definition... */ - pkgXmlNode *cpt = pkg->GetChildren(); - while( cpt != NULL ) + if( cpt->IsElementOfType( component_key ) ) { - /* For each element contained within the "package" definition, - * check if it represents a "component" package definition... + /* ...and return immediately, when it does, AND it also has a + * "name" property which matches the required package name... */ - if( cpt->IsElementOfType( component_key ) ) - { - /* ...and return immediately, when it does, AND it also has a - * "name" property which matches the required package name... - */ - if( strcmp( name, cpt->GetPropVal( name_key, "" )) == 0 ) - return cpt; - - else - { /* We did find a "component" package, but its "name" - * property didn't match; construct an alternative name, - * by combining the "class" property of the "component" - * with the "name" property of the containing "package", - * and evaluate that for a possible match... - */ - const char *pkg_name = pkg->GetPropVal( name_key, "" ); - const char *cpt_class = cpt->GetPropVal( class_key, "" ); - char cpt_name[2 + strlen( pkg_name ) + strlen( cpt_class )]; - sprintf( cpt_name, "%s-%s", pkg_name, cpt_class ); + if( strcmp( name, cpt->GetPropVal( name_key, "" )) == 0 ) + return cpt; + else + { /* We did find a "component" package, but its "name" + * property didn't match; construct an alternative name, + * by combining the "class" property of the "component" + * with the "name" property of the containing "package", + * and evaluate that for a possible match... + */ + const char *cpt_class = cpt->GetPropVal( class_key, "" ); + char *cpt_name = name + len - strlen( cpt_class ); + if( (strcmp( cpt_name, cpt_class ) == 0) + && (*--cpt_name == '-') ) + { /* Again, return the "component", if this identifies * a successful match... */ - if( strcmp( name, cpt_name ) == 0 ) + *cpt_name = '\0'; + if( (strcmp( name, pkg_name ) == 0) || has_keyword( name, alias ) ) return cpt; + + /* Otherwise, restore the original content of the + * working copy of the "lookup name", in preperation + * for any subsequent attempt to find a match. + */ + *cpt_name = '-'; } } - - /* ...otherwise, continue checking any other "components" - * which may be defined within the current "package. - */ - cpt = cpt->GetNext(); } + + /* ...otherwise, continue checking any other "components" + * which may be defined within the current "package. + */ + cpt = cpt->GetNext(); } } -- 2.11.0