aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-08-23 20:47:41 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-08-28 13:15:48 +0200
commit348d6d919c7d128cd6300e9a7f02483850edd079 (patch)
tree1013fff352c89d285cbec91a73aacc1a885ef876
parenta08f2a909f7a67f7ca81354a88b7c2e47dc6f19f (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.h11
-rw-r--r--deps/sysobj_early/src/strstr_word.c56
-rw-r--r--hardinfo/vendor.c206
-rw-r--r--includes/vendor.h24
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__ */