aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-02-26 15:18:45 +0000
committerWerner Koch <[email protected]>2014-02-26 15:18:45 +0000
commitc72762f9acf3eef5c466ba76e895d7654df12ff7 (patch)
treebcb93136c589e406f69ae0d219402c5300d05654
parentcommon: New function get_membuf_shrink. (diff)
downloadgnupg-c72762f9acf3eef5c466ba76e895d7654df12ff7.tar.gz
gnupg-c72762f9acf3eef5c466ba76e895d7654df12ff7.zip
common: New function map_static_macro_string.
* common/mapstrings.c: New. * common/t-mapstrings.c: New. * common/t-support.h (DIM, DIMof): Define if not defined. * common/Makefile.am: Add new files.
-rw-r--r--common/Makefile.am6
-rw-r--r--common/mapstrings.c167
-rw-r--r--common/stringhelp.h4
-rw-r--r--common/t-mapstrings.c101
-rw-r--r--common/t-support.h5
5 files changed, 281 insertions, 2 deletions
diff --git a/common/Makefile.am b/common/Makefile.am
index a777a344b..21f779c8a 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -42,7 +42,7 @@ include $(top_srcdir)/am/cmacros.am
jnlib_sources = \
libjnlib-config.h \
types.h host2net.h dynload.h w32help.h \
- stringhelp.c stringhelp.h \
+ mapstrings.c stringhelp.c stringhelp.h \
strlist.c strlist.h \
utf8conv.c utf8conv.h \
argparse.c argparse.h \
@@ -165,7 +165,8 @@ if HAVE_W32_SYSTEM
jnlib_tests += t-w32-reg
endif
module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil \
- t-session-env t-openpgp-oid t-ssh-utils t-dns-cert
+ t-session-env t-openpgp-oid t-ssh-utils t-dns-cert \
+ t-mapstrings
if !HAVE_W32CE_SYSTEM
module_tests += t-exechelp
endif
@@ -200,3 +201,4 @@ t_session_env_LDADD = $(t_common_ldadd)
t_openpgp_oid_LDADD = $(t_common_ldadd)
t_ssh_utils_LDADD = $(t_common_ldadd)
t_dns_cert_LDADD = $(t_common_ldadd) $(DNSLIBS)
+t_mapstrings_LDADD = $(t_common_ldadd)
diff --git a/common/mapstrings.c b/common/mapstrings.c
new file mode 100644
index 000000000..91795d572
--- /dev/null
+++ b/common/mapstrings.c
@@ -0,0 +1,167 @@
+/* mapstrings.c - Static string mapping
+ * Copyright (C) 2014 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file 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 <config.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "util.h"
+#include "stringhelp.h"
+#include "membuf.h"
+
+
+static struct {
+ const char *name;
+ const char *value;
+} macros[] = {
+#ifdef PACKAGE_BUGREPORT
+ { "EMAIL", PACKAGE_BUGREPORT },
+#else
+ { "EMAIL", "[email protected]" },
+#endif
+ { "GNUPG", GNUPG_NAME },
+ { "GPG", GPG_NAME },
+ { "GPGSM", GPGSM_NAME },
+ { "GPG_AGENT", GPG_AGENT_NAME },
+ { "SCDAEMON", SCDAEMON_NAME },
+ { "DIRMNGR", DIRMNGR_NAME },
+ { "G13", G13_NAME },
+ { "GPGCONF", GPGCONF_NAME },
+ { "GPGTAR", GPGTAR_NAME }
+};
+
+
+
+/* A list to remember already done mappings. */
+struct mapping_s
+{
+ struct mapping_s *next;
+ const char *key;
+ const char *value;
+};
+static struct mapping_s *mappings;
+
+
+/* If STRING has already been mapped, return the mapped string. If
+ not return NULL. */
+static const char *
+already_mapped (const char *string)
+{
+ struct mapping_s *m;
+
+ for (m=mappings; m; m = m->next)
+ if (m->key == string && !strcmp (m->key, string))
+ return m->value;
+ return NULL;
+}
+
+
+/* Store NEWSTRING under key STRING and return NEWSTRING. */
+static const char *
+store_mapping (const char *string, char *newstring)
+{
+ struct mapping_s *m;
+
+ m = xmalloc (sizeof *m);
+ m->key = string;
+ m->value = newstring;
+ m->next = mappings;
+ mappings = m;
+ return newstring;
+}
+
+
+/* Find the first macro in STRING. Return a pointer to the
+ replacement value, set BEGPTR to the leading '@', and set ENDPTR to
+ the terminating '@'. If no macro is found return NULL. */
+const char *
+find_macro (const char *string, const char **begptr,
+ const char **endptr)
+{
+ const char *s, *s2, *s3;
+ int idx;
+
+ s = string;
+ if (!s)
+ return NULL;
+
+ for (; (s2 = strchr (s, '@')); s = s2)
+ {
+ s2++;
+ if (*s2 >= 'A' && *s2 <= 'Z' && (s3 = (strchr (s2, '@'))))
+ {
+ for (idx=0; idx < DIM (macros); idx++)
+ if (strlen (macros[idx].name) == (s3 - s2)
+ && !memcmp (macros[idx].name, s2, (s3 - s2)))
+ {
+ *begptr = s2 - 1;
+ *endptr = s3;
+ return macros[idx].value;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+/* If STRING includes known @FOO@ macros, replace these macros and
+ return a new static string. Warning: STRING must have been
+ allocated statically. Note that this function allocated memory
+ which will not be released (similar to gettext). */
+const char *
+map_static_macro_string (const char *string)
+{
+ const char *s, *s2, *s3, *value;
+ membuf_t mb;
+ char *p;
+
+ if ((s = already_mapped (string)))
+ return s;
+ s = string;
+ value = find_macro (s, &s2, &s3);
+ if (!value)
+ return string; /* No macros at all. */
+
+ init_membuf (&mb, strlen (string) + 100);
+ do
+ {
+ put_membuf (&mb, s, s2 - s);
+ put_membuf_str (&mb, value);
+ s = s3 + 1;
+ }
+ while ((value = find_macro (s, &s2, &s3)));
+ put_membuf_str (&mb, s);
+ put_membuf (&mb, "", 1);
+
+ p = get_membuf_shrink (&mb, NULL);
+ if (!p)
+ log_fatal ("map_static_macro_string failed: %s\n", strerror (errno));
+
+ return store_mapping (string, p);
+}
diff --git a/common/stringhelp.h b/common/stringhelp.h
index c1f7ea12d..21bb20d5a 100644
--- a/common/stringhelp.h
+++ b/common/stringhelp.h
@@ -34,6 +34,7 @@
#include "types.h"
+/*-- stringhelp.c --*/
char *has_leading_keyword (const char *string, const char *keyword);
const char *memistr (const void *buf, size_t buflen, const char *sub);
@@ -145,5 +146,8 @@ char *strconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0);
char *xstrconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0);
+/*-- mapstrings.c --*/
+const char *map_static_macro_string (const char *string);
+
#endif /*LIBJNLIB_STRINGHELP_H*/
diff --git a/common/t-mapstrings.c b/common/t-mapstrings.c
new file mode 100644
index 000000000..14e4bb9ae
--- /dev/null
+++ b/common/t-mapstrings.c
@@ -0,0 +1,101 @@
+/* t-mapstrings.c - Regression tests for mapstrings.c
+ * Copyright (C) 2014 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "stringhelp.h"
+
+#include "t-support.h"
+
+static void
+test_map_static_macro_string (void)
+{
+ static struct {
+ const char *string;
+ const char *expected;
+ const char *lastresult;
+ } tests[] = {
+ { "@GPG@ (@GNUPG@)",
+ GPG_NAME " (" GNUPG_NAME ")" },
+ { "@GPG@(@GNUPG@)",
+ GPG_NAME "(" GNUPG_NAME ")" },
+ { "@GPG@@GNUPG@",
+ GPG_NAME GNUPG_NAME },
+ { " @GPG@@GNUPG@",
+ " " GPG_NAME GNUPG_NAME },
+ { " @GPG@@GNUPG@ ",
+ " " GPG_NAME GNUPG_NAME " " },
+ { " @GPG@GNUPG@ ",
+ " " GPG_NAME "GNUPG@ " },
+ { " @ GPG@GNUPG@ ",
+ " @ GPG" GNUPG_NAME " " },
+ { "--@GPGTAR@",
+ "--" GPGTAR_NAME }
+ };
+ int testno;
+ const char *result;
+
+ for (testno=0; testno < DIM(tests); testno++)
+ {
+ result = map_static_macro_string (tests[testno].string);
+ if (!result)
+ fail (testno);
+ if (strcmp (result, tests[testno].expected))
+ fail (testno);
+ if (!tests[testno].lastresult)
+ tests[testno].lastresult = result;
+ }
+
+ /* A second time to check that the same string is been returned. */
+ for (testno=0; testno < DIM(tests); testno++)
+ {
+ result = map_static_macro_string (tests[testno].string);
+ if (!result)
+ fail (testno);
+ if (strcmp (result, tests[testno].expected))
+ fail (testno);
+ if (result != tests[testno].lastresult)
+ fail (testno);
+ }
+}
+
+
+int
+main (int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ test_map_static_macro_string ();
+
+ return 0;
+}
diff --git a/common/t-support.h b/common/t-support.h
index 8316909b5..0dfcc7a40 100644
--- a/common/t-support.h
+++ b/common/t-support.h
@@ -44,6 +44,11 @@
# define getenv(a) (NULL)
#endif
+#ifndef DIM
+# define DIM(v) (sizeof(v)/sizeof((v)[0]))
+# define DIMof(type,member) DIM(((type *)0)->member)
+#endif
+
/* Replacement prototypes. */
void *gcry_xmalloc (size_t n);