diff options
| author | Burt P <pburt0@gmail.com> | 2019-08-23 20:47:41 -0500 | 
|---|---|---|
| committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2019-08-28 13:15:48 +0200 | 
| commit | 348d6d919c7d128cd6300e9a7f02483850edd079 (patch) | |
| tree | 1013fff352c89d285cbec91a73aacc1a885ef876 | |
| parent | a08f2a909f7a67f7ca81354a88b7c2e47dc6f19f (diff) | |
vendor: update vendor.{h,c}
Mostly new match rules.
Signed-off-by: Burt P <pburt0@gmail.com>
| -rw-r--r-- | deps/sysobj_early/include/strstr_word.h | 11 | ||||
| -rw-r--r-- | deps/sysobj_early/src/strstr_word.c | 56 | ||||
| -rw-r--r-- | hardinfo/vendor.c | 206 | ||||
| -rw-r--r-- | includes/vendor.h | 24 | 
4 files changed, 194 insertions, 103 deletions
diff --git a/deps/sysobj_early/include/strstr_word.h b/deps/sysobj_early/include/strstr_word.h index f607b2ed..f17e78ff 100644 --- a/deps/sysobj_early/include/strstr_word.h +++ b/deps/sysobj_early/include/strstr_word.h @@ -18,13 +18,18 @@   *   */ -/* versions of strstr() and strcasestr() where the match must be preceded and - * succeded by a non-alpha-numeric character. */ -  #ifndef __STRSTR_WORD_H__  #define __STRSTR_WORD_H__ +/* versions of strstr() and strcasestr() where the match must be preceded and + * succeded by a non-alpha-numeric character. */  char *strstr_word(const char *haystack, const char *needle);  char *strcasestr_word(const char *haystack, const char *needle); +/* word boundary at start only (prefix), or end only (suffix) */ +char *strstr_word_prefix(const char *haystack, const char *needle); +char *strcasestr_word_prefix(const char *haystack, const char *needle); +char *strstr_word_suffix(const char *haystack, const char *needle); +char *strcasestr_word_suffix(const char *haystack, const char *needle); +  #endif diff --git a/deps/sysobj_early/src/strstr_word.c b/deps/sysobj_early/src/strstr_word.c index b12f01a2..0b51e4ac 100644 --- a/deps/sysobj_early/src/strstr_word.c +++ b/deps/sysobj_early/src/strstr_word.c @@ -25,40 +25,56 @@  #include <string.h>  #include <ctype.h> -char *strstr_word(const char *haystack, const char *needle) { +static char *_strstr(const char *haystack, const char *needle, int anycase) { +    return anycase +        ? strcasestr(haystack, needle) +        : strstr(haystack, needle); +} + +static char *_strstr_word(const char *haystack, const char *needle, +                          int anycase, int prefix_ok, int suffix_ok) { +      if (!haystack || !needle)          return NULL;      char *c;      const char *p = haystack;      size_t l = strlen(needle); -    while(c = strstr(p, needle)) { +    while((c = _strstr(p, needle, anycase))) {          const char *before = (c == haystack) ? NULL : c-1;          const char *after = c + l; -        int ok = 1; -        if (isalnum(*after)) ok = 0; -        if (before && isalnum(*before)) ok = 0; +        int ok = 1, wbs = 1, wbe = 1; +        if (isalnum(*after)) wbe = 0; +        if (before && isalnum(*before)) wbs = 0; +        if (!wbe && !prefix_ok) ok = 0; +        if (!wbs && !suffix_ok) ok = 0; +        if (!(wbs || wbe)) ok = 0;          if (ok) return c;          p++;      }      return NULL;  } +char *strstr_word(const char *haystack, const char *needle) { +    return _strstr_word(haystack, needle, 0, 0, 0); +} +  char *strcasestr_word(const char *haystack, const char *needle) { -    if (!haystack || !needle) -        return NULL; +    return _strstr_word(haystack, needle, 1, 0, 0); +} -    char *c; -    const char *p = haystack; -    size_t l = strlen(needle); -    while(c = strcasestr(p, needle)) { -        const char *before = (c == haystack) ? NULL : c-1; -        const char *after = c + l; -        int ok = 1; -        if (isalnum(*after)) ok = 0; -        if (before && isalnum(*before)) ok = 0; -        if (ok) return c; -        p++; -    } -    return NULL; +char *strstr_word_prefix(const char *haystack, const char *needle) { +    return _strstr_word(haystack, needle, 0, 1, 0); +} + +char *strcasestr_word_prefix(const char *haystack, const char *needle) { +    return _strstr_word(haystack, needle, 1, 1, 0); +} + +char *strstr_word_suffix(const char *haystack, const char *needle) { +    return _strstr_word(haystack, needle, 0, 0, 1); +} + +char *strcasestr_word_suffix(const char *haystack, const char *needle) { +    return _strstr_word(haystack, needle, 1, 0, 1);  } diff --git a/hardinfo/vendor.c b/hardinfo/vendor.c index fa3b4d96..ff560390 100644 --- a/hardinfo/vendor.c +++ b/hardinfo/vendor.c @@ -58,19 +58,22 @@ static Vendor vendors_builtin[] = {  };  #define ven_msg(msg, ...)  fprintf (stderr, "[%s] " msg "\n", __FUNCTION__, ##__VA_ARGS__) /**/ +#define ven_file_err(msg, ...) {       \ +    ven_msg(msg, ##__VA_ARGS__);       \ +    fflush(stderr);                    \ +    if (vendor_die_on_error) exit(-1); }  static vendor_list vendors = NULL;  const vendor_list get_vendors_list() { return vendors; } +gboolean vendor_die_on_error = FALSE;  /* sort the vendor list by length of match_string,   * LONGEST first */  int vendor_sort (const Vendor *ap, const Vendor *bp) {      int la = 0, lb = 0; -    if (ap && ap->match_string) la = strlen(ap->match_string); -    if (bp && bp->match_string) lb = strlen(bp->match_string); -    if (la == lb) return 0; -    if (la > lb) return -1; -    return 1; +    if (ap) la = ap->weight; +    if (bp) lb = bp->weight; +    return lb-la;  }  static int read_from_vendor_conf(const char *path) { @@ -132,6 +135,7 @@ static int read_from_vendor_ids(const char *path) {      char *wikipedia = vars[4];      char *note = vars[5];      char *ansi_color = vars[6]; +    int name_rule_count = -1;      int count = 0;      FILE *fd; @@ -151,7 +155,7 @@ static int read_from_vendor_ids(const char *path) {          if (b)              *b = 0;          else -            ven_msg("%s:%d: line longer than VEN_BUFF_SIZE (%lu)", path, line, (unsigned long)VEN_BUFF_SIZE); +            ven_file_err("%s:%d: line longer than VEN_BUFF_SIZE (%lu)", path, line, (unsigned long)VEN_BUFF_SIZE);          b = strchr(buff, '#');          if (b) *b = 0; /* line ends at comment */ @@ -159,6 +163,8 @@ static int read_from_vendor_ids(const char *path) {          p = buff;          VEN_FFWD();          if (VEN_CHK("name ")) { +            if (name_rule_count == 0) +                ven_file_err("%s:%d: name \"%s\" had no match rules", path, line, name);              strncpy(name, p + tl, VEN_BUFF_SIZE - 1);              strcpy(name_short, "");              strcpy(url, ""); @@ -166,6 +172,7 @@ static int read_from_vendor_ids(const char *path) {              strcpy(wikipedia, "");              strcpy(note, "");              strcpy(ansi_color, ""); +            name_rule_count = 0;          }          if (VEN_CHK("name_short "))              strncpy(name_short, p + tl, VEN_BUFF_SIZE - 1); @@ -182,12 +189,32 @@ static int read_from_vendor_ids(const char *path) {  #define dup_if_not_empty(s) (strlen(s) ? g_strdup(s) : NULL) -        if (VEN_CHK("match_string ")) { +        int mrule = -1; +        if (VEN_CHK("match_string ")) +            mrule = VENDOR_MATCH_RULE_WORD_IGNORE_CASE; +        else if (VEN_CHK("match_string_case ")) +            mrule = VENDOR_MATCH_RULE_WORD_MATCH_CASE; +        else if (VEN_CHK("match_string_exact ")) +            mrule = VENDOR_MATCH_RULE_EXACT; +        else if (VEN_CHK("match_string_prefix ")) +            mrule = VENDOR_MATCH_RULE_WORD_PREFIX_IGNORE_CASE; +        else if (VEN_CHK("match_string_prefix_case ")) +            mrule = VENDOR_MATCH_RULE_WORD_PREFIX_MATCH_CASE; +        else if (VEN_CHK("match_string_suffix ")) +            mrule = VENDOR_MATCH_RULE_WORD_PREFIX_IGNORE_CASE; +        else if (VEN_CHK("match_string_suffix_case ")) +            mrule = VENDOR_MATCH_RULE_WORD_PREFIX_MATCH_CASE; +        else if (VEN_CHK("match_string_num_prefix ")) +            mrule = VENDOR_MATCH_RULE_NUM_PREFIX_IGNORE_CASE; +        else if (VEN_CHK("match_string_num_prefix_case ")) +            mrule = VENDOR_MATCH_RULE_NUM_PREFIX_MATCH_CASE; + +        if (mrule >= 0) {              Vendor *v = g_new0(Vendor, 1);              v->file_line = line;              v->match_string = g_strdup(p+tl);              v->ms_length = strlen(v->match_string); -            v->match_rule = 0; +            v->match_rule = mrule;              v->name = g_strdup(name);              v->name_short = dup_if_not_empty(name_short);              v->url = dup_if_not_empty(url); @@ -195,47 +222,23 @@ static int read_from_vendor_ids(const char *path) {              v->wikipedia = dup_if_not_empty(wikipedia);              v->note = dup_if_not_empty(note);              v->ansi_color = dup_if_not_empty(ansi_color); -            vendors = g_slist_prepend(vendors, v); -            count++; -        } -        if (VEN_CHK("match_string_case ")) { -            Vendor *v = g_new0(Vendor, 1); -            v->file_line = line; -            v->match_string = g_strdup(p+tl); -            v->ms_length = strlen(v->match_string); -            v->match_rule = 1; -            v->name = g_strdup(name); -            v->name_short = dup_if_not_empty(name_short); -            v->url = dup_if_not_empty(url); -            v->url_support = dup_if_not_empty(url_support); -            v->wikipedia = dup_if_not_empty(wikipedia); -            v->note = dup_if_not_empty(note); -            v->ansi_color = dup_if_not_empty(ansi_color); -            vendors = g_slist_prepend(vendors, v); -            count++; -        } +            v->weight = v->ms_length; +            /* NUM_PREFIX rules consider +1 characters */ +            if (v->match_rule == VENDOR_MATCH_RULE_NUM_PREFIX_MATCH_CASE +                || v->match_rule == VENDOR_MATCH_RULE_NUM_PREFIX_IGNORE_CASE) +                v->weight++; + +            v->has_parens = g_utf8_strchr(v->match_string, -1, '(') ? TRUE : FALSE; -        if (VEN_CHK("match_string_exact ")) { -            Vendor *v = g_new0(Vendor, 1); -            v->file_line = line; -            v->match_string = g_strdup(p+tl); -            v->ms_length = strlen(v->match_string); -            v->match_rule = 2; -            v->name = g_strdup(name); -            v->name_short = dup_if_not_empty(name_short); -            v->url = dup_if_not_empty(url); -            v->url_support = dup_if_not_empty(url_support); -            v->wikipedia = dup_if_not_empty(wikipedia); -            v->note = dup_if_not_empty(note); -            v->ansi_color = dup_if_not_empty(ansi_color);              vendors = g_slist_prepend(vendors, v); +            name_rule_count++;              count++;          }          g_strstrip(buff);          if (!ok && *buff != 0) -            ven_msg("unrecognised item at %s:%d, %s", path, line, p); +            ven_file_err("unrecognised item at %s:%d, %s", path, line, buff);      }      fclose(fd); @@ -487,6 +490,26 @@ vendor_list vendor_list_concat_va(int count, vendor_list vl, ...) {      return ret;  } +int vendor_cmp_deep(const Vendor *a, const Vendor *b) { +    int r; +    if (a && !b) return 1; +    if (!a && b) return -1; +    if (!a && !b) return 0; +    r = g_strcmp0(a->name, b->name); +    if (!!r) return r; +    r = g_strcmp0(a->name_short, b->name_short); +    if (!!r) return r; +    r = g_strcmp0(a->ansi_color, b->ansi_color); +    if (!!r) return r; +    r = g_strcmp0(a->url, b->url); +    if (!!r) return r; +    r = g_strcmp0(a->url_support, b->url_support); +    if (!!r) return r; +    r = g_strcmp0(a->wikipedia, b->wikipedia); +    if (!!r) return r; +    return 0; +} +  vendor_list vendor_list_remove_duplicates_deep(vendor_list vl) {      /* vendor_list is GSList* */      GSList *tvl = vl; @@ -496,13 +519,7 @@ vendor_list vendor_list_remove_duplicates_deep(vendor_list vl) {          evl = tvl->next;          while(evl) {              const Vendor *ev = evl->data; -            if ( SEQ(ev->name, tv->name) -                 && SEQ(ev->name_short, tv->name_short) -                 && SEQ(ev->ansi_color, tv->ansi_color) -                 && SEQ(ev->url, tv->url) -                 && SEQ(ev->url_support, tv->url_support) -                 && SEQ(ev->wikipedia, tv->wikipedia) -                 ) { +            if (vendor_cmp_deep(ev, tv) == 0) {                  GSList *next = evl->next;                  vl = g_slist_delete_link(vl, evl);                  evl = next; @@ -546,54 +563,86 @@ vendor_list vendors_match_core(const gchar *str, int limit) {      int found = 0;      vendor_list ret = NULL; -    /* first pass (passes[1]): ignore text in (), -     *     like (formerly ...) or (nee ...) -     * second pass (passes[0]): full text */ -    gchar *passes[2] = { g_strdup(str), g_strdup(str) }; +    /* pass [array_index]: function +     * 1st [3]: only check match strings that have () in them +     * 2nd [2]: ignore text in (), like (formerly ...) or (nee ...), +     *      but unfortunately also (now ...) +     * 3rd [1]: (passes[0]): full text */ +    gchar *passes[3] = { g_strdup(str), g_strdup(str), g_strdup(str) };      int pass = 1; p = passes[1]; -    while(p = strchr(p, '(') ) { -        pass = 2; p++; +    while((p = strchr(p, '('))) { +        pass = 3; p++;          while(*p && *p != ')') { *p = ' '; p++; }      }      for (; pass > 0; pass--) {          for (vlp = vendors; vlp; vlp = vlp->next) { -            //sysobj_stats.ven_iter++;              Vendor *v = (Vendor *)vlp->data; -            char *m = NULL, *s = NULL; +            char *m = NULL;              if (!v) continue;              if (!v->match_string) continue; +            if (v->has_parens) +                if (pass != 3) continue; + +            //ven_msg("pass:%d <<%s>> EXAMINE: \"%s\"", pass, v->match_string, passes[pass-1]); +            int epass; + +#define standard_match_work_inner(fn) {                       \ +    /* clear so it doesn't match again */                     \ +    for(epass = pass; epass > 0; epass--)                     \ +    {   char *s = passes[epass-1] + (m - passes[pass-1]);     \ +        char *e = s + v->ms_length;                           \ +        for(; s < e; s++) *s = ' ';                           \ +        g_strstrip(passes[epass-1]);  }                       \ +    /* add to return list */                                  \ +    ret = vendor_list_append(ret, v);                         \ +    found++;                                                  \ +    if (*passes[0] == 0)                                      \ +        goto vendors_match_core_finish;                       \ +    if (limit > 0 && found >= limit)                          \ +        goto vendors_match_core_finish; } +#define standard_match_work(fn)                               \ +    if ((m = fn(passes[pass-1], v->match_string)))            \ +        standard_match_work_inner(); +              switch(v->match_rule) { -                case 0: -                    if (m = strcasestr_word(passes[pass-1], v->match_string) ) { -                        /* clear so it doesn't match again */ -                        for(s = m; s < m + v->ms_length; s++) *s = ' '; +                case VENDOR_MATCH_RULE_EXACT: +                    if (SEQ(passes[pass-1], v->match_string) ) {                          /* add to return list */                          ret = vendor_list_append(ret, v);                          found++; -                        if (limit > 0 && found >= limit) -                            goto vendors_match_core_finish; +                        goto vendors_match_core_finish; /* no way for any other match to happen */                      }                      break; -                case 1: /* match case */ -                    if (m = strstr_word(passes[pass-1], v->match_string) ) { -                        /* clear so it doesn't match again */ -                        for(s = m; s < m + v->ms_length; s++) *s = ' '; -                        /* add to return list */ -                        ret = vendor_list_append(ret, v); -                        found++; -                        if (limit > 0 && found >= limit) -                            goto vendors_match_core_finish; -                    } +                case VENDOR_MATCH_RULE_WORD_IGNORE_CASE: +                    standard_match_work(strcasestr_word);                      break; -                case 2: /* match exact */ -                    if (SEQ(passes[pass-1], v->match_string) ) { -                        ret = vendor_list_append(ret, v); -                        found++; -                        goto vendors_match_core_finish; /* no way for any other match to happen */ -                    } +                case VENDOR_MATCH_RULE_WORD_MATCH_CASE: +                    standard_match_work(strstr_word); +                    break; +                case VENDOR_MATCH_RULE_WORD_PREFIX_MATCH_CASE: +                    standard_match_work(strstr_word_prefix); +                    break; +                case VENDOR_MATCH_RULE_WORD_PREFIX_IGNORE_CASE: +                    standard_match_work(strcasestr_word_prefix); +                    break; +                case VENDOR_MATCH_RULE_WORD_SUFFIX_MATCH_CASE: +                    standard_match_work(strstr_word_suffix); +                    break; +                case VENDOR_MATCH_RULE_WORD_SUFFIX_IGNORE_CASE: +                    standard_match_work(strcasestr_word_suffix); +                    break; +                case VENDOR_MATCH_RULE_NUM_PREFIX_IGNORE_CASE: +                    if ((m = strstr_word_prefix(passes[pass-1], v->match_string))) +                        if (isdigit(m[v->ms_length])) +                            standard_match_work_inner(); +                    break; +                case VENDOR_MATCH_RULE_NUM_PREFIX_MATCH_CASE: +                    if ((m = strcasestr_word_prefix(passes[pass-1], v->match_string))) +                        if (isdigit(m[v->ms_length])) +                            standard_match_work_inner();                      break;              }          } @@ -603,5 +652,6 @@ vendors_match_core_finish:      g_free(passes[0]);      g_free(passes[1]); +    g_free(passes[2]);      return ret;  } diff --git a/includes/vendor.h b/includes/vendor.h index 50c23c50..451a6134 100644 --- a/includes/vendor.h +++ b/includes/vendor.h @@ -28,9 +28,22 @@ vendor_list vendor_list_concat_va(int count, vendor_list vl, ...); /* count = -1  #define vendor_list_remove_duplicates(vl) gg_slist_remove_duplicates(vl)  vendor_list vendor_list_remove_duplicates_deep(vendor_list vl); +enum { +  VENDOR_MATCH_RULE_WORD_IGNORE_CASE   = 0, +  VENDOR_MATCH_RULE_WORD_MATCH_CASE    = 1, +  VENDOR_MATCH_RULE_EXACT              = 2, +  VENDOR_MATCH_RULE_WORD_PREFIX_IGNORE_CASE = 3, +  VENDOR_MATCH_RULE_WORD_PREFIX_MATCH_CASE  = 4, +  VENDOR_MATCH_RULE_WORD_SUFFIX_IGNORE_CASE = 5, +  VENDOR_MATCH_RULE_WORD_SUFFIX_MATCH_CASE  = 6, +  /* "ST" hits for "ST3600A" but not "AST" or "STMicro" or "STEC" */ +  VENDOR_MATCH_RULE_NUM_PREFIX_IGNORE_CASE  = 7, +  VENDOR_MATCH_RULE_NUM_PREFIX_MATCH_CASE   = 8, +}; +  typedef struct {    char *match_string; -  int match_rule; /* 0 = ignore case, 1 = match case, 2 = exact */ +  int match_rule; /* VENDOR_MATCH_RULE_* enum */    char *name;    char *name_short;    char *url; @@ -41,11 +54,16 @@ typedef struct {    unsigned long file_line;    unsigned long ms_length; +  unsigned long weight; +  gboolean has_parens;  } Vendor;  void vendor_init(void);  void vendor_cleanup(void); -const Vendor *vendor_match(const gchar *id_str, ...) /* end list of strings with NULL */ +/* end list of strings with NULL */ +const Vendor *vendor_match(const gchar *id_str, ...) +  __attribute__((sentinel)); +vendor_list vendors_match(const gchar *id_str, ...)    __attribute__((sentinel));  const gchar *vendor_get_name(const gchar *id_str);  const gchar *vendor_get_shortest_name(const gchar *id_str); @@ -56,4 +74,6 @@ void vendor_free(Vendor *v);  vendor_list vendors_match_core(const gchar *str, int limit); +extern gboolean vendor_die_on_error; +  #endif	/* __VENDOR_H__ */  | 
