summary refs log tree commit diff stats
path: root/libotr/libgpg-error-1.42/src/mkheader.c
diff options
context:
space:
mode:
Diffstat (limited to 'libotr/libgpg-error-1.42/src/mkheader.c')
-rw-r--r--libotr/libgpg-error-1.42/src/mkheader.c779
1 files changed, 779 insertions, 0 deletions
diff --git a/libotr/libgpg-error-1.42/src/mkheader.c b/libotr/libgpg-error-1.42/src/mkheader.c
new file mode 100644
index 0000000..77826da
--- /dev/null
+++ b/libotr/libgpg-error-1.42/src/mkheader.c
@@ -0,0 +1,779 @@
+/* mkheader.c - Create a header file for libgpg-error
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2014 g10 Code GmbH
+ *
+ * This file is free software; as a special exception the author gives
+ * unlimited permission to copy and/or distribute it, with or without
+ * modifications, as long as this notice is preserved.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define PGM "mkheader"
+
+#define LINESIZE 1024
+
+static char *host_triplet; /* malloced.  */
+static char *host_os;      /* points into host_triplet.  */
+static char *srcdir;
+static const char *hdr_version;
+static const char *hdr_version_number;
+static int cross_building; /* Command line flag.  */
+
+/* Values take from the supplied config.h.  */
+static int have_stdint_h;
+static int have_sys_types_h;
+static int have_w32_system;
+static int have_w64_system;
+static char *replacement_for_off_type;
+static int use_posix_threads;
+
+/* Various state flags.  */
+static int stdint_h_included;
+static int sys_types_h_included;
+
+
+/* The usual free wrapper.  */
+static void
+xfree (void *a)
+{
+  if (a)
+    free (a);
+}
+
+
+static char *
+xmalloc (size_t n)
+{
+  char *p;
+
+  p = malloc (n);
+  if (!p)
+    {
+      fputs (PGM ": out of core\n", stderr);
+      exit (1);
+    }
+  return p;
+}
+
+
+static char *
+xstrdup (const char *string)
+{
+  char *p;
+  size_t len = strlen (string) + 1;
+
+  p = xmalloc (len);
+  memcpy (p, string, len);
+  return p;
+}
+
+
+/* Return a malloced string with TRIPLET.  If TRIPLET has an alias
+ * return that instead.  In general build-aux/config.sub should do the
+ * aliasing but some returned triplets are anyway identical and thus
+ * we use this function to map it to the canonical form.  A pointer to
+ * the OS part of the returned value is stored at R_OS.
+ * NO_VENDOR_HACK is for internal use; caller must call with 0. */
+static char *
+canon_host_triplet (const char *triplet, int no_vendor_hack, char **r_os)
+{
+  struct {
+    const char *name;
+    const char *alias;
+  } tbl[] = {
+    {"i486-pc-linux-gnu", "i686-unknown-linux-gnu" },
+    {"i586-pc-linux-gnu" },
+    {"i686-pc-linux-gnu" },
+    {"arc-oe-linux-gnu"    }, /* Other CPU but same struct.  */
+    {"arc-oe-linux-uclibc" }, /* and uclibc is also the same.  */
+
+    {"i486-pc-gnu", "i686-unknown-gnu"},
+    {"i586-pc-gnu"},
+    {"i686-pc-gnu"},
+
+    {"i486-pc-kfreebsd-gnu", "i686-unknown-kfreebsd-gnu"},
+    {"i586-pc-kfreebsd-gnu"},
+    {"i686-pc-kfreebsd-gnu"},
+
+    {"x86_64-pc-linux-gnuhardened1", "x86_64-unknown-linux-gnu" },
+    {"x86_64-pc-linux-gnu" },
+
+    {"powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu" },
+
+    {"arm-unknown-linux-gnueabihf",  "arm-unknown-linux-gnueabi" },
+    {"armv7-unknown-linux-gnueabihf"  },
+    {"armv7a-unknown-linux-gnueabihf" },
+    {"armv5-unknown-linux-musleabi"   },
+    {"armv6-unknown-linux-musleabihf" },
+
+    { NULL }
+  };
+  int i;
+  const char *lastalias = NULL;
+  const char *s;
+  char *p;
+  char *result;
+
+  for (i=0; tbl[i].name; i++)
+    {
+      if (tbl[i].alias)
+        lastalias = tbl[i].alias;
+      if (!strcmp (tbl[i].name, triplet))
+        {
+          if (!lastalias)
+            break; /* Ooops: first entry has no alias.  */
+          result = xstrdup (lastalias);
+          goto leave;
+        }
+    }
+  for (i=0, s=triplet; *s; s++)
+    if (*s == '-')
+      i++;
+  if (i > 2 && !no_vendor_hack)
+    {
+      /* We have a 4 part "triplet": CPU-VENDOR-KERNEL-SYSTEM where
+       * the last two parts replace the OS part of a real triplet.
+       * The VENDOR part is then in general useless because
+       * KERNEL-SYSTEM is specific enough.  We now do a second pass by
+       * replacing VENDOR with "unknown".  */
+      char *buf = xmalloc (strlen (triplet) + 7 + 1);
+
+      for (p=buf,s=triplet,i=0; *s; s++)
+        {
+          *p++ = *s;
+          if (*s == '-' && ++i == 1)
+            {
+              memcpy (p, "unknown-",8);
+              p += 8;
+              for (s++; *s != '-'; s++)
+                ;
+            }
+        }
+      *p = 0;
+      result = canon_host_triplet (buf, 1, NULL);
+      xfree (buf);
+      goto leave;
+    }
+
+  result = xstrdup (triplet);
+ leave:
+  /* Find the OS part.  */
+  if (r_os)
+    {
+      *r_os = result + strlen (result); /* Default to the empty string.  */
+      for (i=0, p=result; *p; p++)
+        if (*p == '-' && ++i == 2)
+          {
+            *r_os = p+1;
+            break;
+          }
+    }
+
+  return result;
+}
+
+
+/* Parse the supplied config.h file and extract required info.
+   Returns 0 on success.  */
+static int
+parse_config_h (const char *fname)
+{
+  FILE *fp;
+  char line[LINESIZE];
+  int lnr = 0;
+  char *p1;
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    {
+      fprintf (stderr, "%s:%d: can't open file: %s\n",
+               fname, lnr, strerror (errno));
+      return 1;
+    }
+
+  while (fgets (line, LINESIZE, fp))
+    {
+      size_t n = strlen (line);
+
+      lnr++;
+      if (!n || line[n-1] != '\n')
+        {
+          fprintf (stderr,
+                   "%s:%d: trailing linefeed missing, line too long or "
+                   "embedded nul character\n", fname, lnr);
+          break;
+        }
+      line[--n] = 0;
+
+      if (strncmp (line, "#define ", 8))
+        continue; /* We are only interested in define lines.  */
+      p1 = strtok (line + 8, " \t");
+      if (!*p1)
+        continue; /* oops */
+      if (!strcmp (p1, "HAVE_STDINT_H"))
+        have_stdint_h = 1;
+      else if (!strcmp (p1, "HAVE_SYS_TYPES_H"))
+        have_sys_types_h = 1;
+      else if (!strcmp (p1, "HAVE_W32_SYSTEM"))
+        have_w32_system = 1;
+      else if (!strcmp (p1, "HAVE_W64_SYSTEM"))
+        have_w64_system = 1;
+      else if (!strcmp (p1, "REPLACEMENT_FOR_OFF_T"))
+        {
+          p1 = strtok (NULL, "\"");
+          if (!*p1)
+            continue; /* oops */
+          xfree (replacement_for_off_type);
+          replacement_for_off_type = xstrdup (p1);
+        }
+      else if (!strcmp (p1, "USE_POSIX_THREADS"))
+        use_posix_threads = 1;
+    }
+
+  if (ferror (fp))
+    {
+      fprintf (stderr, "%s:%d: error reading file: %s\n",
+               fname, lnr, strerror (errno));
+      return 1;
+    }
+
+  fclose (fp);
+  return 0;
+}
+
+
+/* Write LINE to stdout.  The function is allowed to modify LINE.  */
+static void
+write_str (char *line)
+{
+  if (fputs (line, stdout) == EOF)
+    {
+      fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
+      exit (1);
+    }
+}
+
+static void
+write_line (char *line)
+{
+  if (puts (line) == EOF)
+    {
+      fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
+      exit (1);
+    }
+}
+
+
+/* Write SOURCE or CODES line to stdout.  The function is allowed to
+   modify LINE.  Trailing white space is already removed.  Passing
+   NULL resets the internal state.  */
+static void
+write_sources_or_codes (char *line)
+{
+  static int in_intro;
+  char *p1, *p2;
+
+  if (!line)
+    {
+      in_intro = 1;
+      return;
+    }
+
+  if (!*line)
+    return;
+
+  if (in_intro)
+    {
+      if (!strchr ("0123456789", *line))
+        return;
+      in_intro = 0;
+    }
+
+  p1 = strtok (line, " \t");
+  p2 = p1? strtok (NULL, " \t") : NULL;
+
+  if (p1 && p2 && strchr ("0123456789", *p1) && *p2)
+    {
+      write_str ("    ");
+      write_str (p2);
+      write_str (" = ");
+      write_str (p1);
+      write_str (",\n");
+    }
+}
+
+
+/* Write system errnos to stdout.  The function is allowed to
+   modify LINE.  Trailing white space is already removed.  Passing
+   NULL resets the internal state.  */
+static void
+write_errnos_in (char *line)
+{
+  static int state;
+  char *p1, *p2;
+
+  if (!line)
+    {
+      state = 0;
+      return;
+    }
+
+  if (!*line)
+    return;
+
+  if (!state && strchr ("0123456789", *line))
+    state = 1;
+  else if (state == 1 && !strchr ("0123456789", *line))
+    state = 2;
+
+  if (state != 1)
+    return;
+
+  p1 = strtok (line, " \t");
+  p2 = p1? strtok (NULL, " \t") : NULL;
+
+  if (p1 && p2 && strchr ("0123456789", *p1) && *p2)
+    {
+      write_str ("    GPG_ERR_");
+      write_str (p2);
+      write_str (" = GPG_ERR_SYSTEM_ERROR | ");
+      write_str (p1);
+      write_str (",\n");
+    }
+}
+
+
+/* Create the full file name for NAME and return a newly allocated
+   string with it.  If name contains a '&' and REPL is not NULL
+   replace '&' with REPL. */
+static char *
+mk_include_name (const char *name, const char *repl)
+{
+  FILE *fp;
+  char *incfname, *p;
+  const char *s;
+
+  incfname = malloc (strlen (srcdir) + strlen (name)
+                     + (repl?strlen (repl):0) + 1);
+  if (!incfname)
+    {
+      fputs (PGM ": out of core\n", stderr);
+      exit (1);
+    }
+
+  if (*name == '.' && name[1] == '/')
+    *incfname = 0;
+  else
+    strcpy (incfname, srcdir);
+  p = incfname + strlen (incfname);
+  for (s=name; *s; s++)
+    {
+      if (*s == '&' && repl)
+        {
+          while (*repl)
+            *p++ = *repl++;
+          repl = NULL;  /* Replace only once.  */
+        }
+      else
+        *p++ = *s;
+    }
+  *p = 0;
+  return incfname;
+}
+
+
+/* Include the file NAME from the source directory.  The included file
+   is not further expanded.  It may have comments indicated by a
+   double hash mark at the begin of a line.  OUTF is called for each
+   read line and passed a buffer with the content of line sans line
+   line endings.  If NAME is prefixed with "./" it is included from
+   the current directory and not from the source directory. */
+static void
+include_file (const char *fname, int lnr, const char *name, void (*outf)(char*))
+{
+  FILE *fp;
+  char *incfname;
+  int inclnr;
+  char line[LINESIZE];
+  int repl_flag;
+
+  repl_flag = !!strchr (name, '&');
+  incfname = mk_include_name (name, repl_flag? host_triplet : NULL);
+  fp = fopen (incfname, "r");
+  if (!fp && repl_flag)
+    {
+      /* Try again using the OS string.  */
+      free (incfname);
+      incfname = mk_include_name (name, host_os);
+      fp = fopen (incfname, "r");
+    }
+  if (!fp)
+    {
+      fprintf (stderr, "%s:%d: error including `%s': %s\n",
+               fname, lnr, incfname, strerror (errno));
+      exit (1);
+    }
+
+  if (repl_flag)
+    fprintf (stderr,"%s:%d: note: including '%s'\n",
+             fname, lnr, incfname);
+
+  inclnr = 0;
+  while (fgets (line, LINESIZE, fp))
+    {
+      size_t n = strlen (line);
+
+      inclnr++;
+      if (!n || line[n-1] != '\n')
+        {
+          fprintf (stderr,
+                   "%s:%d: trailing linefeed missing, line too long or "
+                   "embedded nul character\n", incfname, inclnr);
+          fprintf (stderr,"%s:%d: note: file '%s' included from here\n",
+                   fname, lnr, incfname);
+          exit (1);
+        }
+      line[--n] = 0;
+      while (line[n] == ' ' || line[n] == '\t' || line[n] == '\r')
+        {
+          line[n] = 0;
+          if (!n)
+            break;
+          n--;
+        }
+
+      if (line[0] == '#' && line[1] == '#')
+        {
+          if (!strncmp (line+2, "EOF##", 5))
+            break; /* Forced EOF.  */
+        }
+      else
+        outf (line);
+    }
+  if (ferror (fp))
+    {
+      fprintf (stderr, "%s:%d: error reading `%s': %s\n",
+               fname, lnr, incfname, strerror (errno));
+      exit (1);
+    }
+  fclose (fp);
+  free (incfname);
+}
+
+
+/* Try to include the file NAME.  Returns true if it does not
+   exist. */
+static int
+try_include_file (const char *fname, int lnr, const char *name,
+                  void (*outf)(char*))
+{
+  int rc;
+  char *incfname;
+  int repl_flag;
+
+  repl_flag = !!strchr (name, '&');
+  incfname = mk_include_name (name, repl_flag? host_triplet : NULL);
+  rc = access (incfname, R_OK);
+  if (rc && repl_flag)
+    {
+      free (incfname);
+      incfname = mk_include_name (name, host_os);
+      rc = access (incfname, R_OK);
+    }
+  if (!rc)
+    include_file (fname, lnr, name, outf);
+
+  free (incfname);
+  return rc;
+}
+
+
+static int
+write_special (const char *fname, int lnr, const char *tag)
+{
+  if (!strcmp (tag, "version"))
+    {
+      putchar ('\"');
+      fputs (hdr_version, stdout);
+      putchar ('\"');
+    }
+  else if (!strcmp (tag, "version-number"))
+    {
+      fputs (hdr_version_number, stdout);
+    }
+  else if (!strcmp (tag, "define:gpgrt_off_t"))
+    {
+      if (!replacement_for_off_type)
+        {
+          fprintf (stderr, "%s:%d: replacement for off_t not defined\n",
+                   fname, lnr);
+          exit (1);
+        }
+      else
+        {
+          if (!strcmp (replacement_for_off_type, "int64_t")
+              && !stdint_h_included && have_stdint_h)
+            {
+              fputs ("#include <stdint.h>\n\n", stdout);
+              stdint_h_included = 1;
+            }
+          printf ("typedef %s gpgrt_off_t;\n", replacement_for_off_type);
+        }
+    }
+  else if (!strcmp (tag, "define:gpgrt_ssize_t"))
+    {
+      if (have_w64_system)
+        {
+          if (!stdint_h_included && have_stdint_h)
+            {
+              fputs ("# include <stdint.h>\n", stdout);
+              stdint_h_included = 1;
+            }
+          fputs ("typedef int64_t gpgrt_ssize_t;\n", stdout);
+        }
+      else if (have_w32_system)
+        {
+          fputs ("typedef long    gpgrt_ssize_t;\n", stdout);
+        }
+      else
+        {
+          if (!sys_types_h_included)
+            {
+              fputs ("#include <sys/types.h>\n", stdout);
+              sys_types_h_included = 1;
+            }
+          fputs ("typedef ssize_t gpgrt_ssize_t;\n", stdout);
+        }
+    }
+  else if (!strcmp (tag, "api_ssize_t"))
+    {
+      if (have_w32_system)
+        fputs ("gpgrt_ssize_t", stdout);
+      else
+        fputs ("ssize_t", stdout);
+    }
+  else if (!strcmp (tag, "define:pid_t"))
+    {
+      if (have_sys_types_h)
+        {
+          if (!sys_types_h_included)
+            {
+              fputs ("#include <sys/types.h>\n", stdout);
+              sys_types_h_included = 1;
+            }
+        }
+      else if (have_w64_system)
+        {
+          if (!stdint_h_included && have_stdint_h)
+            {
+              fputs ("#include <stdint.h>\n", stdout);
+              stdint_h_included = 1;
+            }
+          fputs ("typedef int64_t pid_t\n", stdout);
+        }
+      else
+        {
+          fputs ("typedef int     pid_t\n", stdout);
+        }
+    }
+  else if (!strcmp (tag, "include:err-sources"))
+    {
+      write_sources_or_codes (NULL);
+      include_file (fname, lnr, "err-sources.h.in", write_sources_or_codes);
+    }
+  else if (!strcmp (tag, "include:err-codes"))
+    {
+      write_sources_or_codes (NULL);
+      include_file (fname, lnr, "err-codes.h.in", write_sources_or_codes);
+    }
+  else if (!strcmp (tag, "include:errnos"))
+    {
+      include_file (fname, lnr, "errnos.in", write_errnos_in);
+    }
+  else if (!strcmp (tag, "include:os-add"))
+    {
+      if (!strcmp (host_os, "mingw32"))
+        {
+          include_file (fname, lnr, "w32-add.h", write_line);
+        }
+      else if (!strcmp (host_os, "mingw32ce"))
+        {
+          include_file (fname, lnr, "w32-add.h", write_line);
+          include_file (fname, lnr, "w32ce-add.h", write_line);
+        }
+    }
+  else if (!strcmp (tag, "include:lock-obj"))
+    {
+      /* If we are not cross compiling and the native file exists we
+       * prefer that over one from syscfg.  */
+      if (cross_building
+          || try_include_file (fname, lnr,
+                               "./lock-obj-pub.native.h", write_line))
+        include_file (fname, lnr, "syscfg/lock-obj-pub.&.h", write_line);
+    }
+  else
+    return 0; /* Unknown tag.  */
+
+  return 1; /* Tag processed.  */
+}
+
+
+int
+main (int argc, char **argv)
+{
+  FILE *fp = NULL;
+  char line[LINESIZE];
+  int lnr = 0;
+  const char *fname, *s;
+  char *p1, *p2;
+  const char *config_h;
+  const char *host_triplet_raw;
+
+  if (argc)
+    {
+      argc--; argv++;
+    }
+  if (argc && !strcmp (argv[0], "--cross"))
+    {
+      cross_building = 1;
+      argc--; argv++;
+    }
+
+  if (argc == 1)
+    {
+      /* Print just the canonicalized host triplet.  */
+      host_triplet = canon_host_triplet (argv[0], 0, &host_os);
+      printf ("%s\n", host_triplet);
+      goto leave;
+    }
+  else if (argc == 5)
+    ; /* Standard operation.  */
+  else
+    {
+      fputs ("usage: " PGM
+             " host_triplet template.h config.h version version_number\n"
+             "       " PGM
+             " host_triplet\n",
+             stderr);
+      return 1;
+    }
+  host_triplet_raw = argv[0];
+  fname = argv[1];
+  config_h = argv[2];
+  hdr_version = argv[3];
+  hdr_version_number = argv[4];
+
+  host_triplet = canon_host_triplet (host_triplet_raw, 0, &host_os);
+
+  srcdir = malloc (strlen (fname) + 2 + 1);
+  if (!srcdir)
+    {
+      fputs (PGM ": out of core\n", stderr);
+      return 1;
+    }
+  strcpy (srcdir, fname);
+  p1 = strrchr (srcdir, '/');
+  if (p1)
+    p1[1] = 0;
+  else
+    strcpy (srcdir, "./");
+
+  if (parse_config_h (config_h))
+    return 1;
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    {
+      fprintf (stderr, "%s:%d: can't open file: %s\n",
+               fname, lnr, strerror (errno));
+      return 1;
+    }
+
+  while (fgets (line, LINESIZE, fp))
+    {
+      size_t n = strlen (line);
+
+      lnr++;
+      if (!n || line[n-1] != '\n')
+        {
+          fprintf (stderr,
+                   "%s:%d: trailing linefeed missing, line too long or "
+                   "embedded nul character\n", fname, lnr);
+          break;
+        }
+      line[--n] = 0;
+
+      p1 = strchr (line, '@');
+      p2 = p1? strchr (p1+1, '@') : NULL;
+      if (!p1 || !p2 || p2-p1 == 1)
+        {
+          puts (line);
+          continue;
+        }
+      *p1++ = 0;
+      *p2++ = 0;
+      fputs (line, stdout);
+
+      if (!strcmp (p1, "configure_input"))
+        {
+          s = strrchr (fname, '/');
+          printf ("Do not edit.  Generated from %s for:\n%*s",
+                  s? s+1 : fname, (int)(p1 - line) + 13, "");
+          if (!strcmp (host_triplet, host_triplet_raw))
+            printf ("%s", host_triplet);
+          else
+            printf ("%s (%s)", host_triplet, host_triplet_raw);
+          if (!use_posix_threads && !have_w32_system && !have_w64_system)
+            fputs (" NO-THREADS", stdout);
+          fputs (p2, stdout);
+        }
+      else if (!write_special (fname, lnr, p1))
+        {
+          putchar ('@');
+          fputs (p1, stdout);
+          putchar ('@');
+          fputs (p2, stdout);
+        }
+      else if (*p2)
+        {
+          fputs (p2, stdout);
+        }
+      putchar ('\n');
+    }
+
+  if (ferror (fp))
+    {
+      fprintf (stderr, "%s:%d: error reading file: %s\n",
+               fname, lnr, strerror (errno));
+      return 1;
+    }
+
+  fputs ("/*\n"
+         "Loc" "al Variables:\n"
+         "buffer-read-only: t\n"
+         "End:\n"
+         "*/\n", stdout);
+
+ leave:
+  if (ferror (stdout))
+    {
+      fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
+      return 1;
+    }
+
+  if (fp)
+    fclose (fp);
+
+  xfree (host_triplet);
+  return 0;
+}