[build-path-prefix-map-spec] 03/50: Add applying examples in C and python

Ximin Luo infinity0 at debian.org
Fri Mar 10 15:17:18 UTC 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository build-path-prefix-map-spec.

commit 1062dd30c16c36e40d1387ec239779d5e76a64f2
Author: Ximin Luo <infinity0 at debian.org>
Date:   Fri Jan 13 19:58:24 2017 +0100

    Add applying examples in C and python
---
 .gitignore          |   1 +
 Makefile            |  22 +++++++++++
 apply.out.1         |   3 ++
 apply.out.2         |   3 ++
 source_prefix_map.h | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 split.c             |  70 +++++++++++++++++++++++++++++++++
 split.py            |  20 ++++++++++
 7 files changed, 228 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8f893d3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/split
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..039bacf
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,22 @@
+ALL = split
+ALL_CHECK = split split.py
+
+.PHONY: all
+all: $(ALL)
+
+%: %.c
+	gcc -o "$@" "$<"
+
+.PHONY: check-apply
+check-apply: apply.out.1 apply.out.2 $(ALL_CHECK)
+	set -ex; for i in $(ALL_CHECK); do \
+	  SOURCE_PREFIX_MAP='/a/b=yyy=ERROR	/a=lol		/b=foo	/a/b=yyy=secreteh' \
+	  ./$$i /a/d /b/1234 /a/b=yyy/xxx | diff -ru - apply.out.1; \
+	done
+	set -ex; for i in $(ALL_CHECK); do \
+	  ./$$i /a/d /b/1234 /a/b=yyy/xxx | diff -ru - apply.out.2; \
+	done
+
+.PHONY: clean
+clean:
+	rm -f $(ALL)
diff --git a/apply.out.1 b/apply.out.1
new file mode 100644
index 0000000..bca0b1d
--- /dev/null
+++ b/apply.out.1
@@ -0,0 +1,3 @@
+lol/d
+foo/1234
+secreteh/xxx
diff --git a/apply.out.2 b/apply.out.2
new file mode 100644
index 0000000..2021286
--- /dev/null
+++ b/apply.out.2
@@ -0,0 +1,3 @@
+/a/d
+/b/1234
+/a/b=yyy/xxx
diff --git a/source_prefix_map.h b/source_prefix_map.h
new file mode 100644
index 0000000..b256095
--- /dev/null
+++ b/source_prefix_map.h
@@ -0,0 +1,109 @@
+/* This file also contains C code, in a real implementation it would be split. */
+
+/* Some memory management primitives, basically copied from GCC. */
+
+#include <malloc.h>
+#include <alloca.h> // this is non-standard but is included in the GCC sources
+#include <string.h>
+
+#define XNEW(T)			((T *) malloc (sizeof (T)))
+#define XNEWVEC(T, N)		((T *) malloc (sizeof (T) * (N)))
+
+char *
+xstrdup (const char *s)
+{
+  register size_t len = strlen (s) + 1;
+  register char *ret = XNEWVEC (char, len);
+  return (char *) memcpy (ret, s, len);
+}
+
+char *
+xstrndup (const char *s, size_t n)
+{
+  char *result;
+  size_t len = strlen (s);
+
+  if (n < len)
+    len = n;
+
+  result = XNEWVEC (char, len + 1);
+
+  result[len] = '\0';
+  return (char *) memcpy (result, s, len);
+}
+
+/* Rest of it, including Applying the variable */
+
+struct prefix_map
+{
+  const char *old_prefix;
+  const char *new_prefix;
+  size_t old_len;
+  size_t new_len;
+  struct prefix_map *next;
+};
+
+const char *
+apply_prefix_map (const char *old_name, char *new_name,
+		  struct prefix_map *map_head)
+{
+  struct prefix_map *map;
+  const char *name;
+
+  for (map = map_head; map; map = map->next)
+    if (strncmp (old_name, map->old_prefix, map->old_len) == 0)
+      break;
+  if (!map)
+    return old_name;
+
+  name = old_name + map->old_len;
+  memcpy (new_name, map->new_prefix, map->new_len);
+  memcpy (new_name + map->new_len, name, strlen (name) + 1);
+  return new_name;
+}
+
+struct prefix_maps
+{
+  struct prefix_map *head;
+  size_t max_replace;
+};
+
+void
+add_prefix_map (struct prefix_map *map, struct prefix_maps *maps)
+{
+  map->next = maps->head;
+  maps->head = map;
+
+  if (map->new_len > maps->max_replace)
+    maps->max_replace = map->new_len;
+}
+
+/*
+ * This function does not consume nor take ownership of filename; the caller is
+ * responsible for freeing it, if and only if it was already responsible for
+ * freeing it before the call.
+ *
+ * It allocates new memory only in the case that a mapping was made. That is,
+ * if and only if filename != return-value, then the caller is responsible for
+ * freeing return-value.
+*/
+const char *
+remap_prefix_alloc (const char *filename, struct prefix_maps *maps, void *(*alloc)(size_t size))
+{
+  size_t maxlen = strlen (filename) + maps->max_replace + 1;
+  char *newname = (char *) alloca (maxlen);
+  const char *name = apply_prefix_map (filename, newname, maps->head);
+
+  if (name == filename)
+    return filename;
+
+  size_t len = strlen (newname) + 1;
+  return (char *) memcpy (alloc (len), newname, len);
+}
+
+// Like remap_prefix_alloc but with the system allocator.
+const char *
+remap_prefix (const char *filename, struct prefix_maps *maps)
+{
+  return remap_prefix_alloc (filename, maps, malloc);
+}
diff --git a/split.c b/split.c
new file mode 100644
index 0000000..a9c92e1
--- /dev/null
+++ b/split.c
@@ -0,0 +1,70 @@
+#include "source_prefix_map.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Parsing the variable. */
+/* For Applying the variable, see source_prefix_map.h. */
+
+int
+parse_prefix_map (const char *arg, struct prefix_map *map)
+{
+  const char *p;
+  p = strrchr (arg, '=');
+  if (!p)
+    return 0;
+  map->old_prefix = xstrndup (arg, p - arg);
+  map->old_len = p - arg;
+  p++;
+  map->new_prefix = xstrdup (p);
+  map->new_len = strlen (p);
+  return 1;
+}
+
+int
+parse_prefix_maps (const char *arg, struct prefix_maps *maps)
+{
+  size_t len = strlen (arg);
+  char *copy = (char *) alloca (len + 1);
+  memcpy (copy, arg, len + 1); // strtok modifies the string so we have to copy it
+
+  char *sep = "\t", *end;
+  char *tok = strtok_r (copy, sep, &end);
+  while (tok != NULL)
+    {
+      struct prefix_map *map = XNEW (struct prefix_map);
+      if (!parse_prefix_map (tok, map))
+	{
+	  fprintf (stderr, "invalid value for prefix-map: %s\n", tok);
+	  free (map);
+	  return 0;
+	}
+
+      add_prefix_map (map, maps);
+      tok = strtok_r (NULL, sep, &end);
+    }
+
+  return 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+  struct prefix_maps source_prefix_map = { NULL, 0 };
+
+  const char *arg;
+  arg = getenv ("SOURCE_PREFIX_MAP");
+  if (arg)
+    if (!parse_prefix_maps (arg, &source_prefix_map))
+      {
+	fprintf (stderr, "parse_prefix_map failed\n");
+	return 1;
+      }
+
+  for (int i = 1; i < argc; i++)
+    {
+      fprintf (stderr, "%s", argv[i]);
+      printf ("%s\n", remap_prefix (argv[i], &source_prefix_map));
+    }
+
+  return 0;
+}
diff --git a/split.py b/split.py
new file mode 100755
index 0000000..041375e
--- /dev/null
+++ b/split.py
@@ -0,0 +1,20 @@
+#!/usr/bin/python3
+
+import os
+import sys
+
+# Parsing the variable
+
+val = os.getenv("SOURCE_PREFIX_MAP", "")
+pm = [r.rsplit("=", 1) for r in reversed(list(filter(None, val.split('\t'))))]
+
+# Applying the variable
+
+def normprefix(string):
+    for src, dst in pm:
+        if string.startswith(src):
+            return dst + string[len(src):]
+    return string
+
+for v in sys.argv[1:]:
+    print(normprefix(v))

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/build-path-prefix-map-spec.git



More information about the Reproducible-commits mailing list