[ros-diffs] [dgorbachev] 44668: Update log2lines to the latest version. Jan Roeloffzen, bug #4342.

dgorbachev at svn.reactos.org dgorbachev at svn.reactos.org
Sun Dec 20 13:36:27 CET 2009


Author: dgorbachev
Date: Sun Dec 20 13:36:26 2009
New Revision: 44668

URL: http://svn.reactos.org/svn/reactos?rev=44668&view=rev
Log:
Update log2lines to the latest version. Jan Roeloffzen, bug #4342.

Modified:
    trunk/reactos/tools/rsym/log2lines.c

Modified: trunk/reactos/tools/rsym/log2lines.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/rsym/log2lines.c?rev=44668&r1=44667&r2=44668&view=diff
==============================================================================
--- trunk/reactos/tools/rsym/log2lines.c [iso-8859-1] (original)
+++ trunk/reactos/tools/rsym/log2lines.c [iso-8859-1] Sun Dec 20 13:36:26 2009
@@ -3,6 +3,7 @@
  * Written by Jan Roeloffzen
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -10,21 +11,30 @@
 
 #include "rsym.h"
 
-#define LOG2LINES_VERSION   "1.8"
+#define LOG2LINES_VERSION   "1.9"
 
 /* Assume if an offset > ABS_TRESHOLD, then it must be absolute */
 #define ABS_TRESHOLD    0x00400000L
 #define INVALID_BASE    0xFFFFFFFFL
 
+#define LOGBOTTOM       "--------"
+#define SVNDB           "svndb.log"
+#define SVNDB_INX       "svndb.inx"
+#define DEF_RANGE       500
+#define MAGIC_INX       0x494E585F //'INX_'
 #define DEF_OPT_DIR     "output-i386"
 #define SOURCES_ENV     "_ROSBE_ROSSOURCEDIR"
 #define CACHEFILE       "log2lines.cache"
 #define TRKBUILDPREFIX  "bootcd-"
+#define SVN_PREFIX      "/trunk/reactos/"
 
 #if defined (__DJGPP__) || defined (__WIN32__)
+
+#include <direct.h>
 
 #define POPEN           _popen
 #define PCLOSE          _pclose
+#define MKDIR(d)        _mkdir(d)
 #define DEV_NULL        "NUL"
 #define DOS_PATHS
 #define PATH_CHAR       '\\'
@@ -35,12 +45,13 @@
 
 #else /* not defined (__DJGPP__) || defined (__WIN32__) */
 
-#include <errno.h>
 #include <limits.h>
+#include <sys/stat.h>
 
 #define MAX_PATH        PATH_MAX
 #define POPEN           popen
 #define PCLOSE          pclose
+#define MKDIR(d)        mkdir(d, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH)
 #define DEV_NULL        "/dev/null"
 #define UNIX_PATHS
 #define PATH_CHAR       '/'
@@ -85,13 +96,13 @@
     struct entry_struct *pnext;
 };
 
-typedef struct entry_struct CACHE_ENTRY;
-
-struct cache_struct
+typedef struct entry_struct LIST_ENTRY;
+
+struct list_struct
 {
     off_t st_size;
-    CACHE_ENTRY *phead;
-    CACHE_ENTRY *ptail;
+    LIST_ENTRY *phead;
+    LIST_ENTRY *ptail;
 };
 
 struct summ_struct
@@ -103,6 +114,7 @@
     int diff;
     int majordiff;
     int revconflicts;
+    int regfound;
     int offset_errors;
     int total;
 };
@@ -122,15 +134,17 @@
 {
     int     rev; 
     int     buildrev;
+    int     range;
     int     opt_verbose;
 };
 
-typedef struct cache_struct CACHE;
+typedef struct list_struct LIST;
 typedef struct summ_struct SUMM;
 typedef struct lineinfo_struct LINEINFO;
 typedef struct revinfo_struct REVINFO;
 
-static CACHE cache;
+static LIST cache;
+static LIST sources;
 static SUMM summ;
 static LINEINFO lastLine;
 static REVINFO revinfo;
@@ -176,6 +190,235 @@
     return 1;
 }
 
+/* Do this in reverse (recursively)
+   This saves many system calls if the path is likely
+   to already exist (creating large trees).
+*/
+static int
+mkPath(char *path, int isDir)
+{
+    char *s;
+    int res = 0;
+
+    if (isDir)
+    {
+        res = MKDIR(path);
+        if (!res || (res == -1 && errno == EEXIST))
+            return 0;
+    }
+    // create parent dir
+    if ((s = strrchr(path, PATH_CHAR)))
+    {
+        *s = '\0';
+        res = mkPath(path, 1);
+        *s = PATH_CHAR;
+    }
+
+    if (!res && isDir)
+        res = MKDIR(path);
+
+    return res;
+}
+
+static FILE *
+rfopen(char *path, char *mode)
+{
+    FILE *f = NULL;
+    char tmppath[MAX_PATH]; // Don't modify const strings
+
+    strcpy(tmppath, path);
+    f = fopen(tmppath, mode);
+    if (!f && !mkPath(tmppath, 0))
+        f = fopen(tmppath, mode);
+    return f;
+}
+
+static LIST_ENTRY *
+entry_lookup(LIST *list, char *name)
+{
+    LIST_ENTRY *pprev = NULL;
+    LIST_ENTRY *pnext;
+
+    if (!name || !name[0])
+        return NULL;
+
+    pnext = list->phead;
+    while (pnext != NULL)
+    {
+        if (PATHCMP(name, pnext->name) == 0)
+        {
+            if (pprev)
+            {   // move to head for faster lookup next time
+                pprev->pnext = pnext->pnext;
+                pnext->pnext = list->phead;
+                list->phead = pnext;
+            }
+            return pnext;
+        }
+        pprev = pnext;
+        pnext = pnext->pnext;
+    }
+    return NULL;
+}
+
+static LIST_ENTRY *
+entry_delete(LIST_ENTRY *pentry)
+{
+    if (!pentry)
+        return NULL;
+    if (pentry->buf)
+        free(pentry->buf);
+    free(pentry);
+    return NULL;
+}
+
+static LIST_ENTRY *
+entry_insert(LIST *list, LIST_ENTRY *pentry)
+{
+    if (!pentry)
+        return NULL;
+
+    pentry->pnext = list->phead;
+    list->phead = pentry;
+    if (!list->ptail)
+        list->ptail = pentry;
+    return pentry;
+}
+
+#if 0
+static LIST_ENTRY *
+entry_remove(LIST *list, LIST_ENTRY *pentry)
+{
+    LIST_ENTRY *pprev = NULL, *p = NULL;
+
+    if (!pentry)
+        return NULL;
+
+    if (pentry == list->phead)
+    {
+        list->phead = pentry->pnext;
+        p = pentry;
+    }
+    else
+    {
+        pprev = list->phead;
+        while (pprev->pnext)
+        {
+            if (pprev->pnext == pentry)
+            {
+                pprev->pnext = pentry->pnext;
+                p = pentry;
+                break;
+            }
+            pprev = pprev->pnext;
+        }
+    }
+    if (pentry == list->ptail)
+        list->ptail = pprev;
+
+    return p;
+}
+#endif
+
+static LIST_ENTRY *
+cache_entry_create(char *Line)
+{
+    LIST_ENTRY *pentry;
+    char *s = NULL;
+    int l;
+
+    if (!Line)
+        return NULL;
+
+    pentry = malloc(sizeof(LIST_ENTRY));
+    if (!pentry)
+        return NULL;
+
+    l = strlen(Line);
+    pentry->buf = s = malloc(l + 1);
+    if (!s)
+    {
+        l2l_dbg(1, "Alloc entry failed\n");
+        return entry_delete(pentry);
+    }
+
+    strcpy(s, Line);
+    if (s[l] == '\n')
+        s[l] = '\0';
+
+    pentry->name = s;
+    s = strchr(s, '|');
+    if (!s)
+    {
+        l2l_dbg(1, "Name field missing\n");
+        return entry_delete(pentry);
+    }
+    *s++ = '\0';
+
+    pentry->path = s;
+    s = strchr(s, '|');
+    if (!s)
+    {
+        l2l_dbg(1, "Path field missing\n");
+        return entry_delete(pentry);
+    }
+    *s++ = '\0';
+    if (1 != sscanf(s, "%x", (unsigned int *)(&pentry->ImageBase)))
+    {
+        l2l_dbg(1, "ImageBase field missing\n");
+        return entry_delete(pentry);
+    }
+    return pentry;
+}
+
+
+static LIST_ENTRY *
+sources_entry_create(LIST *list, char *path, char *prefix)
+{
+    LIST_ENTRY *pentry;
+    char *s = NULL;
+    int l;
+
+    if (!path)
+        return NULL;
+    if (!prefix)
+        prefix = "";
+
+    pentry = malloc(sizeof(LIST_ENTRY));
+    if (!pentry)
+        return NULL;
+
+    l = strlen(path) + strlen(prefix);
+    pentry->buf = s = malloc(l + 1);
+    if (!s)
+    {
+        l2l_dbg(1, "Alloc entry failed\n");
+        return entry_delete(pentry);
+    }
+
+    strcpy(s, prefix);
+    strcat(s, path);
+    if (s[l] == '\n')
+        s[l] = '\0';
+
+    pentry->name = s;
+    if (list)
+    {
+        if (entry_lookup(list, pentry->name))
+        {
+            l2l_dbg(1, "Entry %s exists\n", pentry->name);
+            pentry = entry_delete(pentry);
+        }
+        else
+        {
+            l2l_dbg(1, "Inserting entry %s\n", pentry->name);
+            entry_insert(list, pentry);
+        }
+    }
+
+    return pentry;
+}
+
 static void
 clearLastLine(void)
 {
@@ -198,18 +441,18 @@
         {
             if (lastChanged)
             {
-                if(sscanf(s,"Last Changed Rev: %d",&rev))
+                if (sscanf(s, "Last Changed Rev: %d", &rev))
                     break;
             }
             else
             {
-                if(sscanf(s,"Revision: %d",&rev))
+                if (sscanf(s, "Revision: %d", &rev))
                     break;
             }
         }
     }
     else
-        l2l_dbg(1,"Can't popen: \"%s\"\n", s);
+        l2l_dbg(1, "Can't popen: \"%s\"\n", s);
 
     if (psvn)
         PCLOSE(psvn);
@@ -245,7 +488,7 @@
             *s = PATH_CHAR; // restore
     }
 
-    l2l_dbg(1,"TBRevision: %d\n", rev);
+    l2l_dbg(1, "TBRevision: %d\n", rev);
     return rev;
 }
 
@@ -270,14 +513,14 @@
             {
                 if (i == line)
                     log(outFile, "| ----\n");
-                log(outFile, "| %4.4d  %s", i+1, s);
+                log(outFile, "| %4.4d  %s", i + 1, s);
             }
             i++;
         }
         fclose(src);
     }
     else
-        l2l_dbg(1,"Can't open: %s (check " SOURCES_ENV ")\n", s);
+        l2l_dbg(1, "Can't open: %s (check " SOURCES_ENV ")\n", s);
 }
 
 static void
@@ -334,7 +577,7 @@
 {
     int twice = 0;
 
-    twice = (lastLine.nr2 && (strcmp(lastLine.file1,lastLine.file2) != 0));
+    twice = (lastLine.nr2 && strcmp(lastLine.file1, lastLine.file2) != 0);
     log_rev_check(outFile, lastLine.file1, twice);
     if (twice)
     {
@@ -364,6 +607,15 @@
         return ++base;
     return path;
 }
+
+static void
+report(FILE *outFile)
+{
+    reportRevision(outFile);
+    reportSource(outFile);
+    clearLastLine();
+}
+
 
 static size_t
 fixup_offset(size_t ImageBase, size_t offset)
@@ -439,21 +691,23 @@
         strcpy(lastLine.file1, &Strings[e->FileOffset]);
         strcpy(lastLine.func1, &Strings[e->FunctionOffset]);
         lastLine.nr1 = e->SourceLine;
+        sources_entry_create(&sources, lastLine.file1, SVN_PREFIX);
         lastLine.valid = 1;
         if (e2)
         {
             strcpy(lastLine.file2, &Strings[e2->FileOffset]);
             strcpy(lastLine.func2, &Strings[e2->FunctionOffset]);
             lastLine.nr2 = e2->SourceLine;
+            sources_entry_create(&sources, lastLine.file2, SVN_PREFIX);
             bFileOffsetChanged = e->FileOffset != e2->FileOffset;
             if (e->FileOffset != e2->FileOffset || e->FunctionOffset != e2->FunctionOffset)
                 summ.majordiff++;
 
             /*
-            * - "%.0s" displays nothing, but processes argument
-            * - bFileOffsetChanged implies always display 2nd SourceLine even if the same
-            * - also for FunctionOffset
-            */
+             * - "%.0s" displays nothing, but processes argument
+             * - bFileOffsetChanged implies always display 2nd SourceLine even if the same
+             * - also for FunctionOffset
+             */
             strcat(fmt, "%s");
             if (bFileOffsetChanged)
                 strcat(fmt, "[%s]");
@@ -565,7 +819,7 @@
             sprintf(toString, "??:0");
         else
             printf("??:0");
-        l2l_dbg(1, "Offset not found: %x\n", offset);
+        l2l_dbg(1, "Offset not found: %x\n", (unsigned int)offset);
         summ.offset_errors++;
     }
 
@@ -627,10 +881,16 @@
         l2l_dbg(0, "Cannot remove dst %s before copy\n", dst);
         return 1;
     }
-    system(Line);
+    if (system(Line) < 0)
+    {
+        l2l_dbg(0, "Cannot copy %s to %s\n", src, dst);
+        l2l_dbg(1, "Failed to execute: '%s'\n", Line);
+        return 2;
+    }
+
     if (!file_exists(dst))
     {
-        l2l_dbg(0, "Dst %s does not exist after copy \n", dst);
+        l2l_dbg(0, "Dst %s does not exist after copy\n", dst);
         return 2;
     }
     return 0;
@@ -714,7 +974,7 @@
     if (PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
         PEOptHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
     {
-        l2l_dbg(2, "get_ImageBase %s, not an IMAGE_NT_OPTIONAL_HDR<32|64>\n", fname);
+        l2l_dbg(2, "get_ImageBase %s, not an IMAGE_NT_OPTIONAL_HDR 32/64 bit\n", fname);
         fclose(fr);
         return 6;
     }
@@ -724,110 +984,11 @@
     return 0;
 }
 
-static CACHE_ENTRY *
-entry_delete(CACHE_ENTRY *pentry)
-{
-    if (!pentry)
-        return NULL;
-    if (pentry->buf)
-        free(pentry->buf);
-    free(pentry);
-    return NULL;
-}
-
-static CACHE_ENTRY *
-entry_insert(CACHE_ENTRY *pentry)
-{
-    if (!pentry)
-        return NULL;
-    pentry->pnext = cache.phead;
-    cache.phead = pentry;
-    if (!cache.ptail)
-        cache.ptail = pentry;
-    return pentry;
-}
-
-static CACHE_ENTRY *
-entry_create(char *Line)
-{
-    CACHE_ENTRY *pentry;
-    char *s = NULL;
-    int l;
-
-    if (!Line)
-        return NULL;
-
-    pentry = malloc(sizeof(CACHE_ENTRY));
-    if (!pentry)
-        return NULL;
-
-    l = strlen(Line);
-    pentry->buf = s = malloc(l + 1);
-    if (!s)
-    {
-        l2l_dbg(1, "Alloc entry failed\n");
-        return entry_delete(pentry);
-    }
-
-    strcpy(s, Line);
-    if (s[l] == '\n')
-        s[l] = '\0';
-
-    pentry->name = s;
-    s = strchr(s, '|');
-    if (!s)
-    {
-        l2l_dbg(1, "Name field missing\n");
-        return entry_delete(pentry);
-    }
-    *s++ = '\0';
-
-    pentry->path = s;
-    s = strchr(s, '|');
-    if (!s)
-    {
-        l2l_dbg(1, "Path field missing\n");
-        return entry_delete(pentry);
-    }
-    *s++ = '\0';
-    if (1 != sscanf(s, "%x", &pentry->ImageBase))
-    {
-        l2l_dbg(1, "ImageBase field missing\n");
-        return entry_delete(pentry);
-    }
-    return pentry;
-}
-
-static CACHE_ENTRY *
-entry_lookup(char *name)
-{
-    CACHE_ENTRY *pprev = NULL;
-    CACHE_ENTRY *pnext;
-
-    pnext = cache.phead;
-    while (pnext != NULL)
-    {
-        if (PATHCMP(name, pnext->name) == 0)
-        {
-            if (pprev)
-            {   // move to head for faster lookup next time
-                pprev->pnext = pnext->pnext;
-                pnext->pnext = cache.phead;
-                cache.phead = pnext;
-            }
-            return pnext;
-        }
-        pprev = pnext;
-        pnext = pnext->pnext;
-    }
-    return NULL;
-}
-
 static int
 read_cache(void)
 {
     FILE *fr;
-    CACHE_ENTRY *pentry;
+    LIST_ENTRY *pentry;
     char *Line = NULL;
     int result = 0;
 
@@ -850,13 +1011,13 @@
 
     while (fgets(Line, LINESIZE, fr) != NULL)
     {
-        pentry = entry_create(Line);
+        pentry = cache_entry_create(Line);
         if (!pentry)
         {
             l2l_dbg(2, "** Create entry failed of: %s\n", Line);
         }
         else
-            entry_insert(pentry);
+            entry_insert(&cache, pentry);
     }
 
     fclose(fr);
@@ -908,7 +1069,12 @@
     l2l_dbg(0, "Scanning %s ...\n", opt_dir);
     snprintf(Line, LINESIZE, DIR_FMT, opt_dir, tmp_name);
     l2l_dbg(1, "Executing: %s\n", Line);
-    system(Line);
+    if (system(Line) < 0)
+    {
+        l2l_dbg(0, "Cannot list directory %s\n", opt_dir);
+        l2l_dbg(1, "Failed to execute: '%s'\n", Line);
+        return 2;
+    }
     l2l_dbg(0, "Creating cache ...");
 
     if ((fr = fopen(tmp_name, "r")) != NULL)
@@ -932,9 +1098,9 @@
                 if (*Fname && !skipImageBase)
                 {
                     if ((err = get_ImageBase(Line, &ImageBase)) == 0)
-                        fprintf(fw, "%s|%s|%0x\n", Fname, Line, ImageBase);
+                        fprintf(fw, "%s|%s|%0x\n", Fname, Line, (unsigned int)ImageBase);
                     else
-                        l2l_dbg(3, "%s|%s|%0x, ERR=%d\n", Fname, Line, ImageBase, err);
+                        l2l_dbg(3, "%s|%s|%0x, ERR=%d\n", Fname, Line, (unsigned int)ImageBase, err);
                 }
             }
             fclose(fw);
@@ -951,7 +1117,7 @@
 translate_file(const char *cpath, size_t offset, char *toString)
 {
     size_t base = 0;
-    CACHE_ENTRY *pentry = NULL;
+    LIST_ENTRY *pentry = NULL;
     int res = 0;
     char *path, *dpath;
 
@@ -962,7 +1128,7 @@
     // The path could be absolute:
     if (get_ImageBase(path, &base))
     {
-        pentry = entry_lookup(path);
+        pentry = entry_lookup(&cache, path);
         if (pentry)
         {
             path = pentry->path;
@@ -1033,7 +1199,7 @@
     if (sep)
     {
         *sep = ' ';
-        cnt = sscanf(s, "<%s %x%c", path, &offset, &ch);
+        cnt = sscanf(s, "<%s %x%c", path, (unsigned int *)(&offset), &ch);
         if (opt_undo)
         {
             if (cnt == 3 && ch == ' ')
@@ -1047,12 +1213,12 @@
                     mark = opt_mark ? "* " : "";
                     if (opt_redo && !(res = translate_file(path, offset, LineOut)))
                     {
-                        log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail);
+                        log(outFile, "%s<%s:%x (%s)>%s", mark, path, (unsigned int)offset, LineOut, tail);
                         summ.redo++;
                     }
                     else
                     {
-                        log(outFile, "%s<%s:%x>%s", mark, path, offset, tail);
+                        log(outFile, "%s<%s:%x>%s", mark, path, (unsigned int)offset, tail);
                         summ.undo++;
                     }
                 }
@@ -1073,7 +1239,7 @@
                 if (!(res = translate_file(path, offset, LineOut)))
                 {
                     mark = opt_mark ? "* " : "";
-                    log(outFile, "%s<%s:%x (%s)>%s", mark, path, offset, LineOut, tail);
+                    log(outFile, "%s<%s:%x (%s)>%s", mark, path, (unsigned int)offset, LineOut, tail);
                     summ.translated++;
                 }
                 else
@@ -1094,6 +1260,123 @@
     memset(Line, '\0', LINESIZE);  // flushed
 }
 
+static unsigned long
+findRev(FILE *finx, int *rev)
+{
+    unsigned long pos = 0L;
+
+    while (!fseek(finx, (*rev) * sizeof(unsigned long), SEEK_SET))
+    {
+        fread(&pos, sizeof(long), 1, finx);
+        (*rev)--;
+        if (pos)
+            break;
+    }
+    return pos;
+}
+
+static int
+regscan(FILE *outFile)
+{
+    int res = 0;
+    char logname[MAX_PATH];
+    char inxname[MAX_PATH];
+    char line[LINESIZE + 1];
+    char line2[LINESIZE + 1];
+    FILE *flog = NULL;
+    FILE *finx = NULL;
+    unsigned long pos = 0L;
+    int r;
+
+    sprintf(logname, "%s" PATH_STR "%s", sources_path, SVNDB);
+    sprintf(inxname, "%s" PATH_STR "%s", sources_path, SVNDB_INX);
+    flog = fopen(logname, "rb");
+    finx = fopen(inxname, "rb");
+
+    if (flog && finx)
+    {
+        r = revinfo.buildrev;
+        if (!fread(&pos, sizeof(long), 1, finx))
+        {
+            res = 2;
+            l2l_dbg(0, "Cannot read magic number\n");
+        }
+
+        if (!res)
+        {
+            if (pos != MAGIC_INX)
+            {
+                res = 3;
+                l2l_dbg(0, "Incorrect magic number (%lx)\n", pos);
+            }
+        }
+
+        if (!res)
+        {
+            char flag[2];
+            char path[MAX_PATH];
+            char path2[MAX_PATH];
+            int wflag = 0;
+            log(outFile, "\nRegression candidates:\n");
+            while (( pos = findRev(finx, &r) ))
+            {
+                if (r < (revinfo.buildrev - revinfo.range))
+                {
+                    l2l_dbg(1, "r%d is outside range of %d revisions\n", r, revinfo.range);
+                    break;
+                }
+                fseek(flog, pos, SEEK_SET);
+                wflag = 1;
+                fgets(line, LINESIZE, flog);
+                fgets(line2, LINESIZE, flog);
+                while (fgets(line2, LINESIZE, flog))
+                {
+                    path2[0] = '\0';
+                    if (sscanf(line2, "%1s %s %s", flag, path, path2) >= 2)
+                    {
+                        if (entry_lookup(&sources, path) || entry_lookup(&sources, path2))
+                        {
+                            if (wflag == 1)
+                            {
+                                log(outFile, "%sChanged paths:\n", line);
+                                summ.regfound++;
+                                wflag = 2;
+                            }
+                            log(outFile, "%s", line2);
+                        }
+                    }
+                    else
+                        break;
+                }
+                if (wflag == 2)
+                {
+                    int i = 0;
+                    log(outFile, "\n");
+                    while (fgets(line2, LINESIZE, flog))
+                    {
+                        i++;
+                        log(outFile, "%s", line2);
+                        if (strncmp(LOGBOTTOM, line2, sizeof(LOGBOTTOM) - 1) == 0)
+                            break;
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        res = 1;
+        l2l_dbg(0, "Cannot open %s or %s\n", logname, inxname);
+    }
+
+    if (flog)
+        fclose(flog);
+    if (finx)
+        fclose(finx);
+
+    return res;
+}
+
 static void
 print_summary(FILE *outFile)
 {
@@ -1107,6 +1390,7 @@
         fprintf(outFile, "Differ:                   %d\n", summ.diff);
         fprintf(outFile, "Differ (function/source): %d\n", summ.majordiff);
         fprintf(outFile, "Revision conflicts:       %d\n", summ.revconflicts);
+        fprintf(outFile, "Regression candidates:    %d\n", summ.regfound);
         fprintf(outFile, "Offset error:             %d\n", summ.offset_errors);
         fprintf(outFile, "Total:                    %d\n", summ.total);
         fprintf(outFile, "-------------------------------\n");
@@ -1143,9 +1427,7 @@
                         translate_line(outFile, Line, path, LineOut);
                         i = 0;
                         translate_char(c, outFile);
-                        reportRevision(outFile);
-                        reportSource(outFile);
-                        clearLastLine();
+                        report(outFile);
                         break;
                     case '<':
                         i = 0;
@@ -1198,15 +1480,25 @@
                 if (!opt_raw)
                 {
                     translate_line(outFile, Line, path, LineOut);
-                    reportRevision(outFile);
-                    reportSource(outFile);
-                    clearLastLine();
+                    report(outFile);
                 }
                 else
                     log(outFile, "%s", Line);
             }
         }
     }
+
+    if (opt_Revision && (strstr(opt_Revision, "regscan") == opt_Revision))
+    {
+        char *s = strchr(opt_Revision, ',');
+        if (s)
+        {
+            *s++ = '\0';
+            revinfo.range = atoi(s);
+        }
+        regscan(outFile);
+    }
+
     if (opt_stats)
     {
         print_summary(outFile);
@@ -1227,8 +1519,11 @@
 "      - Also, <offset> can be repeated for each <exefile>\n"
 "      - NOTE: Some of the options below will have no effect in this form.\n"
 "  Otherwise it reads stdin and tries to translate lines of the form:\n"
-"      <IMAGENAME:ADDRESS>\n\n"
-"  The result is written to stdout.\n"
+"      <IMAGENAME:ADDRESS>\n"
+"  The result is written to stdout.\n\n"
+"  <offset> or <ADDRESS> can be absolute or relative with the restrictions:\n"
+"  - An image with base < 0x400000 MUST be relocated to a > 0x400000 address.\n"
+"  - The offset of a relocated image MUST be relative.\n\n"
 "  log2lines uses a cache in order to avoid a directory scan at each\n"
 "  image lookup, greatly increasing performance. Only image path and its\n"
 "  base address are cached.\n\n"
@@ -1266,6 +1561,26 @@
 "         Also when the revison of the source tree is lower than that of the\n"
 "         tested build (for every source file).\n"
 "         In both cases the source file's -S output would be unreliable.\n"
+"       - update:\n"
+"         Updates the SVN log file. Currently only generates the index file\n"
+"         The SVN log file itself must be generated by hand in the sources\n"
+"         directory like this (-v is mandatory here):\n"
+"             svn log -v > svndb.log ('svn log' accepts also a range)\n"
+"         'svndb.log' and its index are needed for '-R regscan'\n"
+"       - regscan[,<range>]:\n"
+"         Scan for regression candidates. Essentially it tries to find\n"
+"         matches between the SVN log entries and the sources hit by\n"
+"         the backtrace.\n"
+"         <range> is the amount of revisions to look back from the build\n"
+"         revision (default 500)\n"
+"         The output of '-R regscan' is printed after EOF. The 'Changed path'\n"
+"         lists will contain only matched files.\n"
+"         Limitations:\n"
+"         - The bug should really be a regression.\n"
+"         - Expect a number of false positives.\n"
+"         - The offending change must be in the sources hit by the backtrace.\n"
+"           This mostly excludes changes in headerfiles for example.\n"
+"         - Must be combined with -S.\n"
 "       Can be combined with -tTS.\n\n"
 "  -s   Statistics. A summary with the following info is printed after EOF:\n"
 "       *** LOG2LINES SUMMARY ***\n"
@@ -1276,6 +1591,7 @@
 "       - Differ:          Lines where (addr-1) info differs. See -tT options\n"
 "       - Differ(func/src):Lines where also function or source info differ.\n"
 "       - Rev conflicts:   Source files conflicting with build. See '-R check'\n"
+"       - Reg candidates:  Regression candidates. See '-R regscan'\n"
 "       - Offset error:    Image exists, but error retrieving offset info.\n"
 "       - Total:           Total number of lines attempted to translate.\n"
 "       Also some version info is displayed.\n\n"
@@ -1425,7 +1741,10 @@
     char *check_dir;
 
     if (opt_Revision)
+    {
         revinfo.rev = getRevision(NULL, 1);
+        revinfo.range = DEF_RANGE;
+    }
     check_iso = strrchr(opt_dir, '.');
     l2l_dbg(1, "Checking directory: %s\n", opt_dir);
     if (check_iso && PATHCMP(check_iso, ".7z") == 0)
@@ -1486,7 +1805,7 @@
     if (opt_Revision)
     {
         revinfo.buildrev = getTBRevision(opt_dir);
-        l2l_dbg(1,"Trunk build revision: %d\n", revinfo.buildrev);
+        l2l_dbg(1, "Trunk build revision: %d\n", revinfo.buildrev);
     }
     cache_name = malloc(MAX_PATH);
     tmp_name = malloc(MAX_PATH);
@@ -1497,6 +1816,49 @@
     return 0;
 }
 
+static int
+updateSvnlog(void)
+{
+    int res = 0;
+    char logname[MAX_PATH];
+    char inxname[MAX_PATH];
+    char line[LINESIZE + 1];
+    FILE *flog = NULL;
+    FILE *finx = NULL;
+    unsigned long pos;
+    int r, y, m, d;
+    char name[NAMESIZE];
+
+    sprintf(logname, "%s" PATH_STR "%s", sources_path, SVNDB);
+    sprintf(inxname, "%s" PATH_STR "%s", sources_path, SVNDB_INX);
+    flog = fopen(logname, "rb");
+    finx = fopen(inxname, "wb");
+
+    if (flog && finx)
+    {
+        pos = MAGIC_INX;
+        fwrite(&pos, sizeof(long), 1, finx);
+        pos = ftell(flog);
+        while (fgets(line, LINESIZE, flog))
+        {
+            if (sscanf(line, "r%d | %s | %d-%d-%d", &r, name, &y, &m, &d) == 5)
+            {
+                l2l_dbg(1, "%ld r%d | %s | %d-%d-%d\n", pos, r, name, y, m, d);
+                fseek(finx, r * sizeof(unsigned long), SEEK_SET);
+                fwrite(&pos, sizeof(unsigned long), 1, finx);
+            }
+            pos = ftell(flog);
+        }
+    }
+
+    if (flog)
+        fclose(flog);
+    if (finx)
+        fclose(finx);
+
+    return res;
+}
+
 int
 main(int argc, const char **argv)
 {
@@ -1509,7 +1871,7 @@
     strcpy(opt_dir, "");
     strcpy(sources_path, "");
     if ((s = getenv(SOURCES_ENV)))
-        strcpy(sources_path,s);
+        strcpy(sources_path, s);
 
     strcpy(opt_scanned, "");
     for (i = 1; i < argc; i++)
@@ -1520,6 +1882,8 @@
     strcpy(opt_logFile, "");
     strcpy(opt_7z, CMD_7Z);
 
+    memset(&cache, 0, sizeof(LIST));
+    memset(&sources, 0, sizeof(LIST));
     memset(&summ, 0, sizeof(SUMM));
     memset(&revinfo, 0, sizeof(REVINFO));
     clearLastLine();
@@ -1566,17 +1930,17 @@
         case 'R':
             optCount++;
             opt_Revision = malloc(LINESIZE);
-            i = sscanf(optarg, "%s", opt_Revision);
+            sscanf(optarg, "%s", opt_Revision);
             break;
         case 's':
             opt_stats++;
             break;
         case 'S':
             optCount++;
-            i = sscanf(optarg, "%d+%d,%s", &opt_Source,&opt_SrcPlus,sources_path);
+            i = sscanf(optarg, "%d+%d,%s", &opt_Source, &opt_SrcPlus, sources_path);
             if (i == 1)
                 sscanf(optarg, "%*d,%s", sources_path);
-            l2l_dbg(3, "Sources option parse result: %d+%d,\"%s\"\n", opt_Source,opt_SrcPlus,sources_path);
+            l2l_dbg(3, "Sources option parse result: %d+%d,\"%s\"\n", opt_Source, opt_SrcPlus, sources_path);
             break;
         case 't':
             opt_twice++;
@@ -1621,8 +1985,14 @@
         strcpy(opt_dir, sources_path);
         strcat(opt_dir, DEF_OPT_DIR);
     }
-
     argc -= optCount;
+
+    if (opt_Revision && (strcmp(opt_Revision, "update") == 0))
+    {
+        res = updateSvnlog();
+        return res;
+    }
+
     if (check_directory(opt_force))
         return 3;
 
@@ -1658,7 +2028,7 @@
     if (argc > 1)
     {   // translate {<exefile> <offset>}
         int i = 1;
-        const char *base = NULL;
+        const char *exefile = NULL;
         const char *offset = NULL;
         char Line[LINESIZE + 1];
 
@@ -1668,14 +2038,12 @@
             offset = argv[optCount + i++];
             if (isOffset(offset))
             {
-                if (base)
+                if (exefile)
                 {
-                    l2l_dbg(2, "translating %s %s\n", base, offset);
-                    translate_file(base, my_atoi(offset), Line);
-                    printf("%s\n", Line); 
-                    reportRevision(stdout);
-                    reportSource(stdout);
-                    clearLastLine();
+                    l2l_dbg(2, "translating %s %s\n", exefile, offset);
+                    translate_file(exefile, my_atoi(offset), Line);
+                    printf("%s\n", Line);
+                    report(stdout);
                 }
                 else
                 {
@@ -1687,7 +2055,7 @@
             else
             {
                 // Not an offset so must be an exefile:
-                base = offset;
+                exefile = offset;
             }
         }
     }




More information about the Ros-diffs mailing list