diff --git a/src/developer_opts.c b/src/developer_opts.c index 1b3d17d9..0f0bdab0 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -44,7 +44,6 @@ #include #include #include -#include #include "avrdude.h" #include "libavrdude.h" @@ -742,6 +741,127 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) { } + +/* + * Match STRING against the partname pattern PATTERN, returning 1 if it + * matches, 0 if not. NOTE: part_match() is a modified old copy of !fnmatch() + * from the GNU C Library (published under GLP v2). Used for portability. + */ + +#define FOLD(c) ({ int _c = (unsigned char) (c); isascii(_c)? tolower(_c): _c; }) + +static int part_match(const char *pattern, const char *string) { + unsigned char c; + const char *p = pattern, *n = string; + + if(!*n) // AVRDUDE specialty: empty string never matches + return 0; + + while((c = FOLD(*p++))) { + switch(c) { + case '?': + if(*n == 0) + return 0; + break; + + case '\\': + c = FOLD(*p++); + if(FOLD(*n) != c) + return 0; + break; + + case '*': + for(c = *p++; c == '?' || c == '*'; c = *p++) + if(c == '?' && *n++ == 0) + return 0; + + if(c == 0) + return 1; + + { + unsigned char c1 = FOLD(c == '\\'? *p : c); // This char + + for(--p; *n; ++n) // Recursively check reminder of string for * + if((c == '[' || FOLD(*n) == c1) && part_match(p, n) == 1) + return 1; + return 0; + } + + case '[': + { + int negate; + + if(*n == 0) + return 0; + + negate = (*p == '!' || *p == '^'); + if(negate) + ++p; + + c = *p++; + for(;;) { + unsigned char cstart = c, cend = c; + + if(c == '\\') + cstart = cend = *p++; + + cstart = cend = FOLD(cstart); + + if(c == 0) // [ (unterminated) + return 0; + + c = *p++; + c = FOLD(c); + + if(c == '-' && *p != ']') { + cend = *p++; + if(cend == '\\') + cend = *p++; + if(cend == 0) + return 0; + cend = FOLD(cend); + + c = *p++; + } + + if(FOLD(*n) >= cstart && FOLD(*n) <= cend) + goto matched; + + if(c == ']') + break; + } + if(!negate) + return 0; + break; + + matched:; + while(c != ']') { // Skip the rest of the [...] that already matched + + if(c == 0) // [... (unterminated) + return 0; + + c = *p++; + if(c == '\\') // XXX 1003.2d11 is unclear if this is right + ++p; + } + if(negate) + return 0; + } + break; + + default: + if(c != FOLD(*n)) + return 0; + } + + ++n; + } + + return *n == 0; +} + + + // -p */[cdosw*] void dev_output_part_defs(char *partdesc) { bool cmdok, waits, opspi, descs, strct, cmpst, raw, all, tsv; @@ -817,8 +937,7 @@ void dev_output_part_defs(char *partdesc) { nprinted = dev_nprinted; } - // pattern match the name of the part with command line: FMP_CASEFOLD not available here :( - if(fnmatch(partdesc, p->desc, 0) && fnmatch(partdesc, p->id, 0)) + if(!part_match(partdesc, p->desc) && !part_match(partdesc, p->id)) continue; if(strct || cmpst)