/* mkheader.c - Create a header file for libassuan.
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* 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.
* SPDX-License-Identifier: FSFULLR
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define PGM "mkheader"
#define LINESIZE 1024
static const char *host_os;
static char *srcdir;
static const char *hdr_version;
static const char *hdr_version_number;
/* Include the file NAME form 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. */
static void
include_file (const char *fname, int lnr, const char *name)
{
FILE *fp;
char *incfname;
char line[LINESIZE];
incfname = malloc (strlen (srcdir) + strlen (name) + 1);
if (!incfname)
{
fputs (PGM ": out of core\n", stderr);
exit (1);
}
strcpy (incfname, srcdir);
strcat (incfname, name);
fp = fopen (incfname, "r");
if (!fp)
{
fprintf (stderr, "%s:%d: error including `%s': %s\n",
fname, lnr, incfname, strerror (errno));
exit (1);
}
while (fgets (line, LINESIZE, fp))
{
if (line[0] == '#' && line[1] == '#')
{
if (!strncmp (line+2, "EOF##", 5))
break; /* Forced EOF. */
}
else
fputs (line, stdout);
}
if (ferror (fp))
{
fprintf (stderr, "%s:%d: error reading `%s': %s\n",
fname, lnr, incfname, strerror (errno));
exit (1);
}
fclose (fp);
free (incfname);
}
static int
write_special (const char *fname, int lnr, const char *tag)
{
if (!strcmp (tag, "include:includes"))
{
if (strstr (host_os, "mingw32"))
include_file (fname, lnr, "w32-includes.inc.h");
else
include_file (fname, lnr, "posix-includes.inc.h");
}
else if (!strcmp (tag, "include:sys/types.h"))
{
if (!strcmp (host_os, "mingw32ce"))
fputs ("#ifdef __MINGW32CE__\n"
"# include <sys/types.h>\n"
"#endif\n", stdout);
else
fputs ("#include <sys/types.h>\n", stdout);
}
else if (!strcmp (tag, "include:unistd.h"))
{
if (!strcmp (host_os, "mingw32ce"))
fputs ("#ifdef __MINGW32CE__\n"
"# include <unistd.h>\n"
"#endif\n", stdout);
else
fputs ("#include <unistd.h>\n", stdout);
}
else if (!strcmp (tag, "include:types"))
{
if (strstr (host_os, "mingw32"))
include_file (fname, lnr, "w32-types.inc.h");
else
include_file (fname, lnr, "posix-types.inc.h");
}
else if (!strcmp (tag, "include:fd-t"))
{
if (!strcmp (host_os, "mingw32ce"))
include_file (fname, lnr, "w32ce-fd-t.inc.h");
else if (strstr (host_os, "mingw32"))
include_file (fname, lnr, "w32-fd-t.inc.h");
else
include_file (fname, lnr, "posix-fd-t.inc.h");
}
else if (!strcmp (tag, "include:sock-nonce"))
{
if (strstr (host_os, "mingw32"))
include_file (fname, lnr, "w32-sock-nonce.inc.h");
else
include_file (fname, lnr, "posix-sock-nonce.inc.h");
}
else if (!strcmp (tag, "include:sys-pth-impl"))
{
if (strstr (host_os, "mingw32"))
include_file (fname, lnr, "w32-sys-pth-impl.h");
else
include_file (fname, lnr, "posix-sys-pth-impl.h");
}
else if (!strcmp (tag, "include:w32ce-add"))
{
if (!strcmp (host_os, "mingw32ce"))
include_file (fname, lnr, "w32ce-add.h");
}
else if (!strcmp (tag, "version"))
{
putchar ('\"');
fputs (hdr_version, stdout);
putchar ('\"');
putchar ('\n');
}
else if (!strcmp (tag, "version-number"))
{
fputs (hdr_version_number, stdout);
putchar ('\n');
}
else
return 0; /* Unknown tag. */
return 1; /* Tag processed. */
}
int
main (int argc, char **argv)
{
FILE *fp;
char line[LINESIZE];
int lnr = 0;
const char *fname, *s;
char *p1, *p2;
if (argc)
{
argc--; argv++;
}
if (argc != 4)
{
fputs ("usage: " PGM " host_os template.h version version_number\n",
stderr);
return 1;
}
host_os = argv[0];
fname = argv[1];
hdr_version = argv[2];
hdr_version_number = argv[3];
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, "./");
fp = fopen (fname, "r");
if (!fp)
{
fprintf (stderr, "%s:%d: can't open file: %s",
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", 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 by %s for %s.",
s? s+1 : fname, PGM, host_os);
fputs (p2, stdout);
putchar ('\n');
}
else if (!write_special (fname, lnr, p1))
{
putchar ('@');
fputs (p1, stdout);
putchar ('@');
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);
if (ferror (stdout))
{
fprintf (stderr, PGM ": error writing stdout: %s\n", strerror (errno));
return 1;
}
fclose (fp);
return 0;
}