Spin mostly complete file classifier off to rpmfc.[ch].
authorjbj <devnull@localhost>
Mon, 14 Oct 2002 14:52:45 +0000 (14:52 +0000)
committerjbj <devnull@localhost>
Mon, 14 Oct 2002 14:52:45 +0000 (14:52 +0000)
CVS patchset: 5773
CVS date: 2002/10/14 14:52:45

build/Makefile.am
build/argv.c
build/argv.h
build/rpmfc.c [new file with mode: 0644]
build/rpmfc.h [new file with mode: 0644]
build/tfr.c

index 3ed2f50..fd6b6da 100644 (file)
@@ -26,14 +26,14 @@ tfr_LDADD = \
 
 pkgincdir = $(pkgincludedir)
 pkginc_HEADERS = rpmbuild.h rpmspec.h
-noinst_HEADERS = argv.h buildio.h
+noinst_HEADERS = argv.h buildio.h rpmfc.h
 
 lib_LTLIBRARIES = librpmbuild.la
 librpmbuild_la_SOURCES = \
        argv.c build.c expression.c files.c misc.c names.c pack.c \
        parseBuildInstallClean.c parseChangelog.c parseDescription.c \
        parseFiles.c parsePreamble.c parsePrep.c parseReqs.c parseScript.c \
-       parseSpec.c poptBT.c reqprov.c spec.c
+       parseSpec.c poptBT.c reqprov.c rpmfc.c spec.c
 librpmbuild_la_LDFLAGS = -release @VERSION@
 
 # XXX Add internal libtool dependence
index 3a84b76..01af214 100644 (file)
@@ -33,16 +33,27 @@ void argvPrint(const char * msg, ARGV_t argv, FILE * fp)
 
 }
 
-int argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
+ARGI_t argiFree(ARGI_t argi)
+{
+    if (argi) {
+       argi->nvals = 0;
+       argi->vals = _free(argi->vals);
+    }
+    argi = _free(argi);
+    return NULL;
+}
+
+ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
 {
     ARGV_t av;
     
-    if ((av = argv)) {
-       while (*av)
-           *av = _free(*av);
-       argv = _free(argv);
-    }
-    return 0;
+/*@-branchstate@*/
+    if (argv)
+    for (av = argv; *av; av++)
+       *av = _free(*av);
+/*@=branchstate@*/
+    argv = _free(argv);
+    return NULL;
 }
 
 int argvCount(/*@null@*/ const ARGV_t argv)
@@ -57,22 +68,64 @@ int argvCount(/*@null@*/ const ARGV_t argv)
 int argvCmp(const void * a, const void * b)
 {
 /*@-boundsread@*/
-    ARG_t astr = *(ARGV_t)a;
-    ARG_t bstr = *(ARGV_t)b;
+    ARGstr_t astr = *(ARGV_t)a;
+    ARGstr_t bstr = *(ARGV_t)b;
 /*@=boundsread@*/
     return strcmp(astr, bstr);
 }
 
 int argvSort(ARGV_t argv, int (*compar)(const void *, const void *))
 {
+    if (compar == NULL)
+       compar = argvCmp;
     qsort(argv, argvCount(argv), sizeof(*argv), compar);
     return 0;
 }
 
-ARGV_t argvSearch(ARGV_t argv, ARG_t s,
+ARGV_t argvSearch(ARGV_t argv, ARGstr_t val,
                int (*compar)(const void *, const void *))
 {
-    return bsearch(&s, argv, argvCount(argv), sizeof(*argv), compar);
+    if (argv == NULL)
+       return NULL;
+    if (compar == NULL)
+       compar = argvCmp;
+    return bsearch(&val, argv, argvCount(argv), sizeof(*argv), compar);
+}
+
+int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val)
+{
+    ARGI_t argi;
+
+    if (argip == NULL)
+       return -1;
+    if (*argip == NULL)
+       *argip = xcalloc(1, sizeof(**argip));
+    argi = *argip;
+    if (ix >= argi->nvals) {
+       argi->vals = xrealloc(argi->vals, (ix + 1) * sizeof(*argi->vals));
+       memset(argi->vals + argi->nvals, 0,
+               (ix - argi->nvals) * sizeof(*argi->vals));
+       argi->nvals = ix + 1;
+    }
+    argi->vals[ix] = val;
+    return 0;
+}
+
+int argvAdd(/*@out@*/ ARGV_t * argvp, ARGstr_t val)
+{
+    ARGV_t argv;
+    int argc;
+
+    if (argvp == NULL)
+       return -1;
+    argc = argvCount(*argvp);
+/*@-unqualifiedtrans@*/
+    *argvp = xrealloc(*argvp, (argc + 1 + 1) * sizeof(**argvp));
+/*@=unqualifiedtrans@*/
+    argv = *argvp;
+    argv[argc++] = xstrdup(val);
+    argv[argc  ] = NULL;
+    return 0;
 }
 
 int argvAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av)
index ae986f3..607be34 100644 (file)
@@ -5,8 +5,15 @@
  * \file build/argv.h
  */
 
-typedef        const char * ARG_t;
-typedef ARG_t * ARGV_t;
+typedef        const char * ARGstr_t;
+typedef ARGstr_t * ARGV_t;
+
+typedef        int * ARGint_t;
+struct ARGI_s {
+    unsigned nvals;
+    ARGint_t vals;
+};
+typedef        struct ARGI_s * ARGI_t;
 
 #ifdef __cplusplus
 extern "C" {
@@ -23,10 +30,21 @@ void argvPrint(const char * msg, ARGV_t argv, FILE * fp)
        /*@modifies *fp, fileSystem @*/;
 
 /**
+ * Destroy an argi array.
+ * @param argi         argi array
+ * @return             NULL always
+ */
+/*@null@*/
+ARGI_t argiFree(/*@only@*/ /*@null@*/ ARGI_t argi)
+       /*@modifies argi @*/;
+
+/**
  * Destroy an argv array.
  * @param argv         argv array
+ * @return             NULL always
  */
-int argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
+/*@null@*/
+ARGV_t argvFree(/*@only@*/ /*@null@*/ ARGV_t argv)
        /*@modifies argv @*/;
 
 /**
@@ -57,14 +75,34 @@ int argvSort(ARGV_t argv, int (*compar)(const void *, const void *))
  * @param argv         argv array
  */
 /*@dependent@*/ /*@null@*/
-ARGV_t argvSearch(ARGV_t argv, ARG_t s,
+ARGV_t argvSearch(ARGV_t argv, ARGstr_t val,
                int (*compar)(const void *, const void *))
        /*@*/;
 
 /**
+ * Add an int to an argi array.
+ * @retval *argip      argi array
+ * @parm ix            argi array index
+ * @param val          int arg to add
+ * @return             0 always
+ */
+int argiAdd(/*@out@*/ ARGI_t * argip, unsigned ix, int val)
+       /*@modifies *argip @*/;
+
+/**
+ * Add a string to an argv array.
+ * @retval *argvp      argv array
+ * @param val          string arg to append
+ * @return             0 always
+ */
+int argvAdd(/*@out@*/ ARGV_t * argvp, ARGstr_t val)
+       /*@modifies *argvp @*/;
+
+/**
  * Append one argv array to another.
  * @retval *argvp      argv array
  * @param av           argv array to append
+ * @return             0 always
  */
 int argvAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av)
        /*@modifies *argvp @*/;
diff --git a/build/rpmfc.c b/build/rpmfc.c
new file mode 100644 (file)
index 0000000..6ec8860
--- /dev/null
@@ -0,0 +1,254 @@
+/*@-bounds@*/
+#include "system.h"
+
+#include <rpmbuild.h>
+#include <argv.h>
+#include <rpmfc.h>
+
+#include "debug.h"
+
+/**
+ */
+/*@unchecked@*/ /*@observer@*/
+static struct fclassTokens_s fclassTokens[] = {
+  { "ELF 32-bit",              RPMFC_ELF32|RPMFC_INCLUDE },
+  { "ELF 64-bit",              RPMFC_ELF64|RPMFC_INCLUDE },
+  { "executable",              RPMFC_EXECUTABLE },
+  { "script",                  RPMFC_SCRIPT },
+  { "text",                    RPMFC_TEXT },
+  { "document",                        RPMFC_DOCUMENT },
+
+  { "directory",               RPMFC_DIRECTORY|RPMFC_INCLUDE },
+
+  { "statically linked",       RPMFC_STATIC },
+  { "not stripped",            RPMFC_NOTSTRIPPED },
+  { "compressed",              RPMFC_COMPRESSED },
+  { "font",                    RPMFC_FONT },
+
+  { "current ar archive",      RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE },
+  { " font",                   RPMFC_FONT|RPMFC_INCLUDE },
+  { " Font",                   RPMFC_FONT|RPMFC_INCLUDE },
+
+  { "Zip archive data",                RPMFC_COMPRESSED|RPMFC_ARCHIVE|RPMFC_INCLUDE },
+  { "tar archive",             RPMFC_ARCHIVE|RPMFC_INCLUDE },
+  { "cpio archive",            RPMFC_ARCHIVE|RPMFC_INCLUDE },
+  { "RPM v3",                  RPMFC_ARCHIVE|RPMFC_INCLUDE },
+
+  { "shell script",            RPMFC_SCRIPT|RPMFC_INCLUDE },
+  { "awk script",              RPMFC_SCRIPT|RPMFC_INCLUDE },
+  { "perl script",             RPMFC_SCRIPT|RPMFC_INCLUDE },
+  { "python script",           RPMFC_SCRIPT|RPMFC_INCLUDE },
+
+  { "python compiled",         RPMFC_SCRIPT|RPMFC_INCLUDE },
+  { "PHP script",              RPMFC_SCRIPT|RPMFC_INCLUDE },
+
+  { "empty",                   RPMFC_WHITE|RPMFC_INCLUDE },
+
+  { "HTML",                    RPMFC_WHITE|RPMFC_INCLUDE },
+  { "SGML",                    RPMFC_WHITE|RPMFC_INCLUDE },
+  { "XML",                     RPMFC_WHITE|RPMFC_INCLUDE },
+
+  { " program text",           RPMFC_WHITE|RPMFC_INCLUDE },
+  { " source",                 RPMFC_WHITE|RPMFC_INCLUDE },
+  { "GLS_BINARY_LSB_FIRST",    RPMFC_WHITE|RPMFC_INCLUDE },
+  { " DB ",                    RPMFC_WHITE|RPMFC_INCLUDE },
+
+  { "ASCII English text",      RPMFC_WHITE|RPMFC_INCLUDE },
+  { "ASCII text",              RPMFC_WHITE|RPMFC_INCLUDE },
+  { "ISO-8859 text",           RPMFC_WHITE|RPMFC_INCLUDE },
+
+  { "symbolic link to",                RPMFC_SYMLINK },
+
+  { "ASCII",                   RPMFC_WHITE },
+  { "ISO-8859",                        RPMFC_WHITE },
+
+  { "data",                    RPMFC_WHITE },
+
+  { "application",             RPMFC_WHITE },
+  { "boot",                    RPMFC_WHITE },
+  { "catalog",                 RPMFC_WHITE },
+  { "code",                    RPMFC_WHITE },
+  { "file",                    RPMFC_WHITE },
+  { "format",                  RPMFC_WHITE },
+  { "message",                 RPMFC_WHITE },
+  { "program",                 RPMFC_WHITE },
+  { "text",                    RPMFC_WHITE },
+
+  { "broken symbolic link to ",        RPMFC_WHITE|RPMFC_ERROR },
+  { "can't read",              RPMFC_WHITE|RPMFC_ERROR },
+  { "can't stat",              RPMFC_WHITE|RPMFC_ERROR },
+  { "executable, can't read",  RPMFC_WHITE|RPMFC_ERROR },
+  { "core file",               RPMFC_WHITE|RPMFC_ERROR },
+
+  { NULL,                      RPMFC_BLACK }
+};
+
+/*@unchecked@*/
+static int fcolorIgnore =
+    (RPMFC_ELF32|RPMFC_ELF64|RPMFC_DIRECTORY|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_FONT|RPMFC_SCRIPT|RPMFC_WHITE);
+
+int fclassColoring(const char * fmstr)
+{
+    fclassToken fct;
+    int fcolor = RPMFC_BLACK;
+
+    for (fct = fclassTokens; fct->token != NULL; fct++) {
+       if (strstr(fmstr, fct->token) == NULL)
+           continue;
+       fcolor |= fct->colors;
+       if (fcolor & RPMFC_INCLUDE)
+           return fcolor;
+    }
+    return fcolor;
+}
+
+void fclassPrint(const char * msg, FCLASS_t fc, FILE * fp)
+{
+    int ac = 0;
+    int fcolor;
+    int ix;
+
+    if (fp == NULL) fp = stderr;
+
+    if (msg)
+       fprintf(fp, "===================================== %s\n", msg);
+
+    if (fc)
+    while (1) {
+       if (fc->fn[ac] == NULL)
+           break;
+       if (ac >= fc->fdictx->nvals)
+           break;
+       ix = fc->fdictx->vals[ac];
+       if (ix < 0)
+           break;
+
+       fcolor = fc->fcolor->vals[ac];
+       if (ix > 0 && !(fcolor & fcolorIgnore)) {
+           fprintf(fp, "%3d %s", ix, fc->fn[ac]);
+           if (fcolor != RPMFC_BLACK)
+               fprintf(fp, "\t0x%x", fc->fcolor->vals[ac]);
+           else
+               fprintf(fp, "\t%s", fc->dict[ix]);
+           fprintf(fp, "\n");
+       }
+
+       ac++;
+    }
+}
+
+FCLASS_t fclassFree(FCLASS_t fc)
+{
+    if (fc) {
+       fc->fn = argvFree(fc->fn);
+       fc->fdictx = argiFree(fc->fdictx);
+       fc->fcolor = argiFree(fc->fcolor);
+       fc->dict = argvFree(fc->dict);
+    }
+    fc = _free(fc);
+    return NULL;
+}
+
+FCLASS_t fclassNew(void)
+{
+    FCLASS_t fc = xcalloc(1, sizeof(*fc));
+    return fc;
+}
+
+int fclassClassify(FCLASS_t *fcp, ARGV_t argv)
+{
+    FCLASS_t fc;
+    char buf[BUFSIZ];
+    ARGV_t dav;
+    const char * s, * se;
+    char * t;
+    int fcolor;
+    int xx;
+    int fknown, fwhite;
+
+
+    if (fcp == NULL || argv == NULL)
+       return 0;
+
+    if (*fcp == NULL)
+       *fcp = fclassNew();
+    fc = *fcp;
+
+    /* Set up the file class dictionary. */
+    xx = argvAdd(&fc->dict, "");
+    xx = argvAdd(&fc->dict, "directory");
+
+/*@-temptrans@*/
+    fc->av = argv;
+/*@=temptrans@*/
+    while ((s = *fc->av++) != NULL) {
+       se = s;
+       while (*se && !(se[0] == ':' && se[1] == ' '))
+           se++;
+       if (*se == '\0')
+           return -1;
+
+       se++;
+       while (*se && (*se == ' ' || *se == '\t'))
+           se++;
+       if (*se == '\0')
+           return -1;
+
+       fcolor = fclassColoring(se);
+       if (fcolor == RPMFC_WHITE || !(fcolor & RPMFC_INCLUDE))
+           continue;
+
+       dav = argvSearch(fc->dict, se, NULL);
+       if (dav == NULL) {
+           xx = argvAdd(&fc->dict, se);
+           xx = argvSort(fc->dict, NULL);
+       }
+    }
+
+    /* Classify files. */
+/*@-kepttrans@*/
+    fc->av = argv;
+/*@=kepttrans@*/
+    fc->ix = 0;
+    fknown = 0;
+    while ((s = *fc->av++) != NULL) {
+       se = s;
+       while (*se && !(se[0] == ':' && se[1] == ' '))
+           se++;
+       if (*se == '\0')
+           return -1;
+
+       t = stpncpy(buf, s, (se - s));
+       *t = '\0';
+
+       xx = argvAdd(&fc->fn, buf);
+
+       se++;
+       while (*se && (*se == ' ' || *se == '\t'))
+           se++;
+       if (*se == '\0')
+           return -1;
+
+       dav = argvSearch(fc->dict, se, NULL);
+       if (dav) {
+           xx = argiAdd(&fc->fdictx, fc->ix, (dav - fc->dict));
+           fknown++;
+       } else {
+           xx = argiAdd(&fc->fdictx, fc->ix, 0);
+           fwhite++;
+       }
+
+       xx = argiAdd(&fc->fcolor, fc->ix, fclassColoring(se));
+
+       fc->ix++;
+    }
+    fc->av = NULL;
+
+/*@-modfilesys@*/
+sprintf(buf, "final: files %d dict[%d] %d%%", argvCount(fc->fn), argvCount(fc->dict), ((100 * fknown)/fc->ix));
+fclassPrint(buf, fc, NULL);
+/*@=modfilesys@*/
+
+    return 0;
+}
+/*@=bounds@*/
diff --git a/build/rpmfc.h b/build/rpmfc.h
new file mode 100644 (file)
index 0000000..c922972
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef _H_RPMFC_
+#define _H_RPMFC_
+
+typedef struct fclass_s * FCLASS_t;
+
+struct fclass_s {
+    ARGV_t av;         /*!< file(1) output lines */
+    int ac;            /*!< no. of lines */
+    int ix;            /*!< current lineno */
+    ARGV_t fn;         /*!< file names */
+    ARGI_t fcolor;     /*!< file colors */
+    ARGI_t fdictx;     /*!< file class dictionary indices */
+    ARGV_t dict;       /*!< file class dictionary */
+};
+
+
+enum FCOLOR_e {
+    RPMFC_BLACK                        = 0,
+    RPMFC_ELF32                        = (1 <<  0),
+    RPMFC_ELF64                        = (1 <<  1),
+
+    RPMFC_EXECUTABLE           = (1 <<  2),
+    RPMFC_SCRIPT               = (1 <<  3),
+    RPMFC_TEXT                 = (1 <<  4),
+
+    RPMFC_DIRECTORY            = (1 <<  8),
+    RPMFC_LIBRARY              = (1 <<  9),
+    RPMFC_DOCUMENT             = (1 << 10),
+
+    RPMFC_STATIC               = (1 << 16),
+    RPMFC_NOTSTRIPPED          = (1 << 18),
+    RPMFC_COMPRESSED           = (1 << 19),
+
+    RPMFC_SYMLINK              = (1 << 24),
+    RPMFC_ARCHIVE              = (1 << 25),
+    RPMFC_FONT                 = (1 << 26),
+
+    RPMFC_WHITE                        = (1 << 29),
+    RPMFC_INCLUDE              = (1 << 30),
+    RPMFC_ERROR                        = (1 << 31)
+};
+typedef        enum FCOLOR_e FCOLOR_t;
+
+struct fclassTokens_s {
+/*@observer@*/
+    const char * token;
+    int colors;
+};
+
+typedef struct fclassTokens_s * fclassToken;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ */
+int fclassColoring(const char * fmstr)
+       /*@*/;
+
+/**
+ */
+void fclassPrint(const char * msg, FCLASS_t fc, FILE * fp)
+       /*@globals fileSystem @*/
+       /*@modifies *fp, fileSystem @*/;
+/**
+ */
+/*@null@*/
+FCLASS_t fclassFree(/*@only@*/ /*@null@*/ FCLASS_t fc)
+       /*@modifies fc @*/;
+
+/**
+ */
+FCLASS_t fclassNew(void)
+       /*@*/;
+
+/**
+ */
+int fclassClassify(/*@out@*/ FCLASS_t *fcp, ARGV_t argv)
+       /*@modifies *fcp @*/;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H_RPMFC_ */
index 46c7623..66726c2 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <rpmbuild.h>
 #include <argv.h>
+#include <rpmfc.h>
 
 #include "debug.h"
 
@@ -25,6 +26,7 @@ main(int argc, char *const argv[])
     int pac = 0;
     ARGV_t xav;
     ARGV_t av = NULL;
+    FCLASS_t fc;
     int ac = 0;
     const char * s;
     int ec = 1;
@@ -50,23 +52,23 @@ main(int argc, char *const argv[])
     xav = NULL;
     xx = argvAppend(&xav, pav);
     xx = argvAppend(&xav, av);
-    pav = _free(pav);
+    pav = _free(pav);  /* XXX popt mallocs in single blob. */
     s = _free(s);
 
     /* Read file(1) output. */
     sb = getOutputFrom(NULL, xav, NULL, 0, 1);
+    xav = argvFree(xav);
 
-    xx = argvFree(xav);
-
-    xav = NULL;
     xx = argvSplit(&xav, getStringBuf(sb), "\n");
     sb = freeStringBuf(sb);
 
     xx = argvSort(xav, argvCmp);
 
-argvPrint("final", xav, NULL);
+    fc = NULL;
+    xx = fclassClassify(&fc, xav);
+    fc = fclassFree(fc);
 
-    xx = argvFree(xav);
+    xav = argvFree(xav);
 
 exit:
     optCon = rpmcliFini(optCon);