Skip to content
Snippets Groups Projects
filevercmp.h.patch 7.99 KiB
Newer Older
Author: Andreas Tille <tille@debian.org>
Last-Update: Thu, 23 Jun 2016 09:10:54 +0200
Origin: https://github.com/ekg/filevercmp
Description: Inject two files via quilt patch
 It would be better to use filevercmp module from gnulib package via
    gnulib-tool --import filevercmp
 but this would require configure.ac which is not (yet) done.
 .
 Upstream provides a copy of the code inside gnulib at
    https://github.com/ekg/filevercmp
 and thus it seems to be simpler to use this here at least for the moment.

--- a/Makefile
+++ b/Makefile
@@ -191,7 +191,12 @@ $(FASTAHACK): pre
 #	cd fsom && $(CXX) $(CXXFLAGS) -c fsom.c -lm
 
 $(FILEVERCMP): pre
-	cd filevercmp && make && cp *.h* $(VCF_LIB_LOCAL)/$(INC_DIR)/ && cp *.o $(VCF_LIB_LOCAL)/$(INC_DIR)/
+	#mkdir -p filevercmp
+	#cp /usr/share/gnulib/lib/filevercmp.* filevercmp
+	#echo 'Proper use of filevercmp would be: `gnulib-tool --import filevercmp` - but it needs ./configure.ac'
+	#We here go with quilt patches from upstream files
+	cd filevercmp && $(CXX) $(CXXFLAGS) -c filevercmp.c
+	ln -sf ../filevercmp/filevercmp.h $(VCF_LIB_LOCAL)/$(INC_DIR)/filevercmp.h
 
 $(SHORTBINS): pre
 	$(MAKE) bin/$@
--- /dev/null
+++ b/filevercmp/filevercmp.h
Gert Wollny's avatar
Gert Wollny committed
@@ -0,0 +1,51 @@
+/*
+   Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+   Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
+   Copyright (C) 2008-2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef FILEVERCMP_H
+#define FILEVERCMP_H
+
+/* Compare version strings:
+
+   This function compares strings S1 and S2:
+   1) By PREFIX in the same way as strcmp.
+   2) Then by VERSION (most similarly to version compare of Debian's dpkg).
+      Leading zeros in version numbers are ignored.
+   3) If both (PREFIX and  VERSION) are equal, strcmp function is used for
+      comparison. So this function can return 0 if (and only if) strings S1
+      and S2 are identical.
+
+   It returns number >0 for S1 > S2, 0 for S1 == S2 and number <0 for S1 < S2.
+
+   This function compares strings, in a way that if VER1 and VER2 are version
+   numbers and PREFIX and SUFFIX (SUFFIX defined as (\.[A-Za-z~][A-Za-z0-9~]*)*)
+   are strings then VER1 < VER2 implies filevercmp (PREFIX VER1 SUFFIX,
+   PREFIX VER2 SUFFIX) < 0.
+
+   This function is intended to be a replacement for strverscmp. */
Gert Wollny's avatar
Gert Wollny committed
+
+#ifdef __cplusplus
+extern "C" {
+#endif   
+
+int filevercmp (const char *s1, const char *s2);
+
Gert Wollny's avatar
Gert Wollny committed
+#ifdef __cplusplus
+}
+#endif   
+
+#endif /* FILEVERCMP_H */
--- /dev/null
+++ b/filevercmp/filevercmp.c
@@ -0,0 +1,180 @@
+/*
+   Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+   Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
+   Copyright (C) 2008-2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include "filevercmp.h"
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+/* Match a file suffix defined by this regular expression:
+   /(\.[A-Za-z~][A-Za-z0-9~]*)*$/
+   Scan the string *STR and return a pointer to the matching suffix, or
+   NULL if not found.  Upon return, *STR points to terminating NUL.  */
+static const char *
+match_suffix (const char **str)
+{
+  const char *match = NULL;
+  bool read_alpha = false;
+  while (**str)
+    {
+      if (read_alpha)
+        {
+          read_alpha = false;
+          if (!isalpha (**str) && '~' != **str)
+            match = NULL;
+        }
+      else if ('.' == **str)
+        {
+          read_alpha = true;
+          if (!match)
+            match = *str;
+        }
+      else if (!isalnum (**str) && '~' != **str)
+        match = NULL;
+      (*str)++;
+    }
+  return match;
+}
+
+/* verrevcmp helper function */
+static inline int
+order (unsigned char c)
+{
+  if (isdigit (c))
+    return 0;
+  else if (isalpha (c))
+    return c;
+  else if (c == '~')
+    return -1;
+  else
+    return (int) c + UCHAR_MAX + 1;
+}
+
+/* slightly modified verrevcmp function from dpkg
+   S1, S2 - compared string
+   S1_LEN, S2_LEN - length of strings to be scanned
+
+   This implements the algorithm for comparison of version strings
+   specified by Debian and now widely adopted.  The detailed
+   specification can be found in the Debian Policy Manual in the
+   section on the `Version' control field.  This version of the code
+   implements that from s5.6.12 of Debian Policy v3.8.0.1
+   http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */
+static int
+verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
+{
+  size_t s1_pos = 0;
+  size_t s2_pos = 0;
+  while (s1_pos < s1_len || s2_pos < s2_len)
+    {
+      int first_diff = 0;
+      while ((s1_pos < s1_len && !isdigit (s1[s1_pos]))
+	     || (s2_pos < s2_len && !isdigit (s2[s2_pos])))
+	{
+	  int s1_c = (s1_pos == s1_len) ? 0 : order (s1[s1_pos]);
+	  int s2_c = (s2_pos == s2_len) ? 0 : order (s2[s2_pos]);
+	  if (s1_c != s2_c)
+	    return s1_c - s2_c;
+	  s1_pos++;
+	  s2_pos++;
+	}
+      while (s1[s1_pos] == '0')
+	s1_pos++;
+      while (s2[s2_pos] == '0')
+	s2_pos++;
+      while (isdigit (s1[s1_pos]) && isdigit (s2[s2_pos]))
+	{
+	  if (!first_diff)
+	    first_diff = s1[s1_pos] - s2[s2_pos];
+	  s1_pos++;
+	  s2_pos++;
+	}
+      if (isdigit (s1[s1_pos]))
+	return 1;
+      if (isdigit (s2[s2_pos]))
+	return -1;
+      if (first_diff)
+	return first_diff;
+    }
+  return 0;
+}
+
+/* Compare version strings S1 and S2.
+   See filevercmp.h for function description.  */
+int
+filevercmp (const char *s1, const char *s2)
+{
+  const char *s1_pos;
+  const char *s2_pos;
+  const char *s1_suffix, *s2_suffix;
+  size_t s1_len, s2_len;
+  int result;
+
+  /* easy comparison to see if strings are identical */
+  int simple_cmp = strcmp (s1, s2);
+  if (simple_cmp == 0)
+    return 0;
+
+  /* special handle for "", "." and ".." */
+  if (!*s1)
+    return -1;
+  if (!*s2)
+    return 1;
+  if (0 == strcmp (".", s1))
+    return -1;
+  if (0 == strcmp (".", s2))
+    return 1;
+  if (0 == strcmp ("..", s1))
+    return -1;
+  if (0 == strcmp ("..", s2))
+    return 1;
+
+  /* special handle for other hidden files */
+  if (*s1 == '.' && *s2 != '.')
+    return -1;
+  if (*s1 != '.' && *s2 == '.')
+    return 1;
+  if (*s1 == '.' && *s2 == '.')
+    {
+      s1++;
+      s2++;
+    }
+
+  /* "cut" file suffixes */
+  s1_pos = s1;
+  s2_pos = s2;
+  s1_suffix = match_suffix (&s1_pos);
+  s2_suffix = match_suffix (&s2_pos);
+  s1_len = (s1_suffix ? s1_suffix : s1_pos) - s1;
+  s2_len = (s2_suffix ? s2_suffix : s2_pos) - s2;
+
+  /* restore file suffixes if strings are identical after "cut" */
+  if ((s1_suffix || s2_suffix) && (s1_len == s2_len)
+      && 0 == strncmp (s1, s2, s1_len))
+    {
+      s1_len = s1_pos - s1;
+      s2_len = s2_pos - s2;
+    }
+
+  result = verrevcmp (s1, s1_len, s2, s2_len);
+  return result == 0 ? simple_cmp : result;
+}